| /** @file |
| |
| A brief file description |
| |
| @section license License |
| |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| #ifndef __ABSTRACT_BUFFER_H__ |
| #define __ABSTRACT_BUFFER_H__ |
| |
| |
| #include "libts.h" |
| |
| |
| enum ABError |
| { |
| AB_ERROR_OK, |
| AB_ERROR_BUSY, |
| AB_ERROR_STATE, |
| AB_ERROR_FULL, |
| AB_ERROR_OFFSET |
| }; |
| |
| |
| class AbstractBuffer |
| { |
| public: |
| enum AbstractBufferState |
| { |
| AB_STATE_UNUSED, |
| AB_STATE_INITIALIZING, |
| AB_STATE_READ_WRITE, |
| AB_STATE_READ_ONLY, |
| AB_STATE_FLUSH, |
| AB_STATE_FLUSH_COMPLETE |
| }; |
| |
| protected: |
| union VolatileState |
| { |
| VolatileState() |
| { |
| ival = 0; |
| } |
| |
| VolatileState(volatile VolatileState & vs) |
| { |
| ival = vs.ival; |
| } |
| |
| VolatileState & operator =(volatile VolatileState & vs) |
| { |
| ival = vs.ival; |
| return *this; |
| } |
| |
| int64_t ival; |
| struct |
| { |
| uint16_t reader_count; |
| uint16_t writer_count; |
| uint32_t offset:29; |
| uint32_t state:3; |
| } s; |
| }; |
| |
| public: |
| AbstractBuffer(int xsize, int xalignment) |
| : buffer(NULL), unaligned_buffer(NULL), size(xsize), alignment(xalignment) |
| { |
| clear(); |
| } |
| virtual ~ AbstractBuffer() { |
| clear(); |
| } |
| |
| char *data() |
| { |
| return buffer; |
| } |
| char &operator [] (int idx) |
| { |
| ink_assert(idx >= 0); |
| ink_assert(idx < size); |
| return buffer[idx]; |
| } |
| int offset() |
| { |
| return vs.s.offset; |
| } |
| |
| virtual ABError checkout_write(int *write_offset, int write_size, uint64_t retries = (uint64_t) - 1); |
| virtual ABError checkout_read(int read_offset, int read_size); |
| virtual ABError checkin_write(int write_offset); |
| virtual ABError checkin_read(int read_offset); |
| |
| virtual void initialize(); |
| virtual void full(); |
| virtual void flush(); |
| virtual void flush_complete(); |
| virtual void destroy(); |
| virtual void clear(); |
| |
| bool switch_state(VolatileState & old_state, VolatileState & new_state); |
| |
| public: |
| volatile VolatileState vs; |
| char *buffer; |
| char *unaligned_buffer; |
| int size; |
| int alignment; |
| |
| public: |
| VolatileState vs_history[AB_STATE_FLUSH_COMPLETE + 1]; |
| }; |
| |
| |
| class AbstractBufferReader |
| { |
| public: |
| AbstractBufferReader(AbstractBuffer * xbuffer, int xoffset) |
| : buffer(xbuffer), offset(xoffset) |
| { |
| } |
| |
| ~AbstractBufferReader() |
| { |
| buffer->checkin_read(offset); |
| } |
| |
| private: |
| AbstractBuffer * buffer; |
| int offset; |
| }; |
| |
| |
| class AbstractBufferWriter |
| { |
| public: |
| AbstractBufferWriter(AbstractBuffer * xbuffer, int xoffset) |
| : buffer(xbuffer), offset(xoffset) |
| { |
| } |
| |
| ~AbstractBufferWriter() |
| { |
| buffer->checkin_write(offset); |
| } |
| |
| private: |
| AbstractBuffer * buffer; |
| int offset; |
| }; |
| |
| /*------------------------------------------------------------------------- |
| -------------------------------------------------------------------------*/ |
| |
| inline bool |
| AbstractBuffer::switch_state(VolatileState & old_vs, VolatileState & new_vs) |
| { |
| if (ink_atomic_cas((int64_t *) & vs.ival, old_vs.ival, new_vs.ival)) { |
| return true; |
| } |
| |
| return false; |
| } |
| |
| #endif /* __ABSTRACT_BUFFER_H__ */ |