inital commit
[c11concurrency-benchmarks.git] / mabain / src / lock_free.h
1 /**
2  * Copyright (C) 2017 Cisco Inc.
3  *
4  * This program is free software: you can redistribute it and/or  modify
5  * it under the terms of the GNU General Public License, version 2,
6  * as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15  */
16
17 // @author Changxue Deng <chadeng@cisco.com>
18
19 #ifndef __LOCK_FREE_H__
20 #define __LOCK_FREE_H__
21
22 #include <stdint.h>
23 #include <string.h>
24 #include <atomic>
25
26 #include "mb_data.h"
27
28 namespace mabain {
29
30 // C++11 std::atomic shared memory variable for lock-free
31 // reader/writer concurrency.
32
33 #define MAX_OFFSET_CACHE   4
34 #define MEMORY_ORDER_WRITER std::memory_order_release
35 #define MEMORY_ORDER_READER std::memory_order_consume
36
37 struct _IndexHeader;
38 typedef struct _IndexHeader IndexHeader;
39
40 typedef struct _LockFreeData
41 {
42     uint32_t counter;
43     size_t   offset;
44 } LockFreeData;
45
46 typedef struct _LockFreeShmData
47 {
48     std::atomic<uint32_t> counter;
49     std::atomic<size_t>   offset;
50     std::atomic<size_t>   offset_cache[MAX_OFFSET_CACHE];
51 } LockFreeShmData;
52
53 class LockFree
54 {
55 public:
56     LockFree();
57     ~LockFree();
58
59     void LockFreeInit(LockFreeShmData *lock_free_ptr, IndexHeader *hdr, int mode = 0);
60     inline void WriterLockFreeStart(size_t offset);
61     void WriterLockFreeStop();
62     inline void ReaderLockFreeStart(LockFreeData &snapshot);
63     // If there was race condition, this function returns MBError::TRY_AGAIN.
64     int  ReaderLockFreeStop(const LockFreeData &snapshot, size_t reader_offset,
65              MBData &mbdata);
66
67 private:
68     LockFreeShmData *shm_data_ptr;
69     const IndexHeader *header;
70 };
71
72 inline void LockFree::WriterLockFreeStart(size_t offset)
73 {
74     shm_data_ptr->offset.store(offset, MEMORY_ORDER_WRITER);
75 }
76
77 inline void LockFree::ReaderLockFreeStart(LockFreeData &snapshot)
78 {
79     snapshot.counter = shm_data_ptr->counter.load(MEMORY_ORDER_READER);
80 }
81
82 }
83
84 #endif