[dali_2.3.23] Merge branch 'devel/master'
[platform/core/uifw/dali-core.git] / dali / integration-api / lockless-buffer.h
1 #ifndef DALI_INTEGRATION_LOCKLESS_BUFFER_H
2 #define DALI_INTEGRATION_LOCKLESS_BUFFER_H
3
4 /*
5  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // EXTERNAL INCLUDES
22 #include <cstdint> // uint32_t, uint8_t
23
24 // INTERNAL INCLUDES
25 #include <dali/public-api/common/dali-common.h>
26 #include <dali/public-api/common/vector-wrapper.h>
27 #include <cstring>
28
29 namespace Dali
30 {
31 namespace Integration
32 {
33 /**
34  * The LocklessBuffer class implements double buffering eligible for multi-(two) threaded use,
35  * where it's possible to read from one thread and write from another
36  * without requiring a mutex lock to avoid performance hit.
37  * It's intended to be used for reading bitmap data in render thread
38  * while still possible to write data in another thread.
39  *
40  * Ideally Write() and Read() calls should be alternating, otherwise written data might be thrown away.
41  *
42  * The buffers are swapped in the reading thread, just before reading begins.
43  * In case the other thread is writing at that moment, buffers are not swapped and previously available data is read.
44  * Similarly if Write() is called before a Read() has finished the previous write buffer is overwritten.
45  */
46 class DALI_CORE_API LocklessBuffer
47 {
48 public:
49   /**
50    * Constructor.
51    * @param[in] size The size of buffers in bytes.
52    */
53   LocklessBuffer(uint32_t size);
54
55   /**
56    * Destructor.
57    */
58   ~LocklessBuffer();
59
60   /**
61    * Write data to buffer.
62    * @param[in] src data source
63    * @param[in] size size of data in bytes
64    */
65   void Write(const uint8_t* src, uint32_t size);
66
67   /**
68    * Try to swap buffers and read data.
69    * @note returned value only valid until Read() is called again or object is destroyed
70    * @return current read buffer contents
71    */
72   const uint8_t* Read();
73
74   /**
75    * @return the buffer size in bytes
76    */
77   uint32_t GetSize() const;
78
79 private:
80   /**
81    * Atomically set state.
82    * We're always writing to one buffer and reading from the other.
83    * Write() sets WRITING bit when started and unsets it when finished.
84    */
85   enum BufferState
86   {
87     R0W1              = 0, ///< Read from buffer 0 write to buffer 1
88     R1W0              = 1, ///< Read from buffer 1 write to buffer 0
89     WRITING           = 2, ///< Currently writing to buffer
90     UPDATED           = 4, ///< Swapping buffer required; there is new data available
91     WRITE_BUFFER_MASK = 1, ///< indicates which buffer to write to
92     WRITING_MASK      = 2, ///< indicates whether currently writing
93     UPDATED_MASK      = 4  ///< indicates whether new data is available
94   };
95
96 private:
97   LocklessBuffer();                                 ///< undefined default constructor, need to give size on construction
98   LocklessBuffer(const LocklessBuffer&);            ///< undefined copy constructor
99   LocklessBuffer& operator=(const LocklessBuffer&); ///< undefined assignment operator
100
101 private:
102   uint8_t* mBuffer[2];         ///< bitmap buffers
103   BufferState volatile mState; ///< readbuffer number and whether we're currently writing into writebuffer or not
104   uint32_t mSize;              ///< size of buffers
105 };
106
107 } // namespace Integration
108
109 } // namespace Dali
110
111 #endif // DALI_INTEGRATION_LOCKLESS_BUFFER_H