// Returns with writer_lock held. static void* cl_block_start_write(cl_block* block, size_t size) { if (!cl_try_lock(&block->writer_lock)) { return NULL; } size_t bytes_committed = cl_block_get_bytes_committed(block); if (bytes_committed + size > CENSUS_LOG_MAX_RECORD_SIZE) { cl_unlock(&block->writer_lock); return NULL; } return block->buffer + bytes_committed; }
/* Returns a pointer to the first unread byte in buffer. The number of bytes available are returned in 'bytes_available'. Acquires reader lock that is released by a subsequent cl_block_end_read() call. Returns NULL if: - read in progress - no data available */ static void *cl_block_start_read(cl_block *block, size_t *bytes_available) { void *record; if (!cl_try_lock(&block->reader_lock)) { return NULL; } /* bytes_committed may change from under us. Use bytes_available to update bytes_read below. */ *bytes_available = cl_block_get_bytes_committed(block) - block->bytes_read; if (*bytes_available == 0) { cl_unlock(&block->reader_lock); return NULL; } record = block->buffer + block->bytes_read; block->bytes_read += *bytes_available; return record; }
// Returns a pointer to the first unread byte in buffer. The number of bytes // available are returned in 'bytes_available'. Acquires reader lock that is // released by a subsequent cl_block_end_read() call. Returns NULL if: // - read in progress // - no data available static void* cl_block_start_read(cl_block* block, size_t* bytes_available) { if (!cl_try_lock(&block->reader_lock)) { return NULL; } // bytes_committed may change from under us. Use bytes_available to update // bytes_read below. size_t bytes_committed = cl_block_get_bytes_committed(block); GPR_ASSERT(bytes_committed >= block->bytes_read); *bytes_available = bytes_committed - block->bytes_read; if (*bytes_available == 0) { cl_unlock(&block->reader_lock); return NULL; } void* record = block->buffer + block->bytes_read; block->bytes_read += *bytes_available; return record; }
// Tries to disable future read/write access to this block. Succeeds if: // - no in-progress write AND // - no in-progress read AND // - 'discard_data' set to true OR no unread data // On success, clears the block state and returns with writer_lock_ and // reader_lock_ held. These locks are released by a subsequent // cl_block_access_enable() call. static bool cl_block_try_disable_access(cl_block* block, int discard_data) { if (!cl_try_lock(&block->writer_lock)) { return false; } if (!cl_try_lock(&block->reader_lock)) { cl_unlock(&block->writer_lock); return false; } if (!discard_data && (block->bytes_read != cl_block_get_bytes_committed(block))) { cl_unlock(&block->reader_lock); cl_unlock(&block->writer_lock); return false; } cl_block_set_bytes_committed(block, 0); block->bytes_read = 0; return true; }
// Releases writer_lock and increments committed bytes by 'bytes_written'. // 'bytes_written' must be <= 'size' specified in the corresponding // StartWrite() call. This function is thread-safe. static void cl_block_end_write(cl_block* block, size_t bytes_written) { cl_block_set_bytes_committed( block, cl_block_get_bytes_committed(block) + bytes_written); cl_unlock(&block->writer_lock); }