EpcTools
An event based multi-threaded C++ development framework.
esynch.h
Go to the documentation of this file.
1 /*
2 * Copyright (c) 2009-2019 Brian Waters
3 * Copyright (c) 2019 Sprint
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 
18 #ifndef __esynch_h_included
19 #define __esynch_h_included
20 
23 
24 #include <semaphore.h>
25 
26 #include "ebase.h"
27 #include "estring.h"
28 #include "eerror.h"
29 
30 #define MAX_SEMIDS 64
31 #define MAX_NOTIFYIDS 64
32 
35 
37 DECLARE_ERROR_ADVANCED2(EMutexError_UnableToInitialize);
38 DECLARE_ERROR_ADVANCED2(EMutexError_UnableToLock);
39 DECLARE_ERROR_ADVANCED2(EMutexError_UnableToUnLock);
40 DECLARE_ERROR(EMutexError_UnableToAllocateMutex);
41 DECLARE_ERROR(EMutexError_AlreadyInitialized);
42 DECLARE_ERROR(EMutexError_MutexUninitialized);
43 
46 
47 DECLARE_ERROR_ADVANCED(ESemaphoreError_UnableToInitialize);
48 DECLARE_ERROR_ADVANCED(ESemaphoreError_UnableToDecrement);
49 DECLARE_ERROR_ADVANCED(ESemaphoreError_UnableToIncrement);
50 
51 DECLARE_ERROR(ESemaphoreError_UnableToAllocateSemaphore);
52 DECLARE_ERROR(ESemaphoreError_AlreadyAllocated);
53 DECLARE_ERROR(ESemaphoreError_NotInitialized);
54 DECLARE_ERROR(ESemaphoreError_AlreadyInitialized);
55 DECLARE_ERROR(ESemaphoreError_MaxNotifyIdsExceeded);
57 
59 // Common Mutex Classes
61 
62 // class EMutexPrivate;
63 // class EMutexPublic;
64 // class EMutexLock;
65 
73 {
74  friend class EMutexPrivate;
75  friend class EMutexPublic;
76  friend class EMutexLock;
77 
78 public:
81  {
82  }
83 
87  Void init(Bool shared);
89  Void destroy();
90 
93  Bool initialized()
94  {
95  return m_initialized;
96  }
97 
99 #if defined(NATIVE_IPC)
100  pthread_mutex_t &mutex()
102  {
103  return m_mutex;
104  }
105 #else
106  Long &mutex()
108  {
109  return m_lock;
110  }
111 #endif
112 
113 protected:
115  EMutexData()
116  {
117  m_initialized = False;
118  }
119  Bool enter(Bool wait = True);
120  Void leave();
122 
123 private:
124  Bool m_initialized;
125 #if defined(NATIVE_IPC)
126  pthread_mutex_t m_mutex;
127 #else
128  Long m_lock;
129 #endif
130 };
131 
134 {
135 public:
140  : m_acquire(acquire), m_mtx(mtx)
141  {
142  if (m_acquire)
143  m_mtx.enter();
144  }
147  {
148  if (m_acquire)
149  m_mtx.leave();
150  }
151 
155  Bool acquire(Bool wait = True)
156  {
157  if (!m_acquire)
158  m_acquire = m_mtx.enter(wait);
159  return m_acquire;
160  }
161 
162 private:
163  Bool m_acquire;
164  EMutexData &m_mtx;
165 
166  EMutexLock();
167  EMutexLock &operator=(const EMutexLock &other);
168 };
169 
171 // Private Mutex Classes
173 
175 class EMutexPrivate : public EMutexData
176 {
177 public:
180  EMutexPrivate(Bool bInit = True)
181  : EMutexData()
182  {
183  if (bInit)
184  init();
185  }
188  {
189  destroy();
190  }
191 
193  Void *operator new(size_t, Void *where) { return where; }
194 
196 };
197 
199 // Public Mutex Classes
201 
203 class EMutexDataPublic : public EMutexData
204 {
205  friend class ESynchObjects;
206 
207 public:
208  ~EMutexDataPublic() {}
209 
210  Int &mutexId() { return m_mutexId; }
211 
212 protected:
213  EMutexDataPublic() {}
214  Int &nextIndex() { return m_nextIndex; }
215 
216 private:
217  Int m_nextIndex;
218  Int m_mutexId;
219 };
221 
224 {
225 public:
228  EMutexPublic(Bool bInit = True)
229  {
230  m_mutexid = 0;
231  if (bInit)
232  init();
233  }
236  {
237  destroy();
238  }
239 
241  Void init();
243  Void destroy();
244 
247  Void attach(Int mutexid);
249  Void detach();
250 
253  Int mutexId() { return m_mutexid; }
254 
257  operator EMutexDataPublic &();
258 
259 private:
260  Int m_mutexid;
261 };
262 
264 // Common Semaphore Classes
266 
269 {
270 public:
273  : m_initialized(False),
274  m_shared(False),
275  m_initCount(0),
276  m_currCount(0)
277  {
278  }
282  ESemaphoreData(Long initcnt, Bool shared)
283  : m_initialized(False),
284  m_shared(shared),
285  m_initCount(initcnt),
286  m_currCount(0)
287  {
288  }
291  {
292  destroy();
293  }
294 
296  Void init();
298  Void destroy();
299 
304  Bool Decrement(Bool wait = True);
307  Bool Increment();
308 
311  Bool initialized() { return m_initialized; }
314  Bool &shared() { return m_shared; }
317  Long &initialCount() { return m_initCount; }
320  Long currCount() { return m_currCount; }
321 
322 private:
323  Bool m_initialized;
324  Bool m_shared;
325  Long m_initCount;
326  Long m_currCount;
327  sem_t m_sem;
328 };
329 
332 {
333 public:
338 
341  virtual Void init(Long initcnt) = 0;
343  virtual Void destroy() = 0;
344 
348  Bool Decrement(Bool wait = True) { return getData().Decrement(wait); }
351  Bool Increment() { return getData().Increment(); }
352 
355  Bool initialized() { return getData().initialized(); }
358  Bool &shared() { return getData().shared(); }
361  Long &initialCount() { return getData().initialCount(); }
364  Long currCount() { return getData().currCount(); }
365 
368  operator ESemaphoreData&() { return getData(); }
369 
370 protected:
372  virtual ESemaphoreData &getData() = 0;
374 };
375 
377 // Private Semaphore Classes
379 
383 {
384 public:
388  ESemaphorePrivate(Long initcnt=0, Bool bInit = True)
389  : m_data(initcnt, False)
390  {
391  if (bInit)
392  init(initcnt);
393  }
396  {
397  destroy();
398  }
399 
402  Void init(Long initcnt) { m_data.initialCount() = initcnt; m_data.init(); }
404  Void destroy() { m_data.destroy(); }
405 
406 protected:
408  ESemaphoreData &getData() { return m_data; }
410 
411 private:
412  ESemaphoreData m_data;
413 };
414 
416 // Public Semaphore Classes
418 
420 class ESemaphoreDataPublic : public ESemaphoreData
421 {
422  friend class ESemaphorePublic;
423  friend class ESynchObjects;
424 public:
425  ESemaphoreDataPublic(Long initcnt=0)
426  : ESemaphoreData(initcnt, True)
427  {
428  }
429  ~ESemaphoreDataPublic()
430  {
431  }
432 
433  Int &semIndex() { return m_semIndex; }
434 
435 protected:
436  Int &nextIndex() { return m_nextIndex; }
437 
438 private:
439  Int m_nextIndex;
440  Int m_semIndex;
441 };
443 
447 {
448  friend class ESynchObjects;
449 public:
452  : m_semid(0)
453  {
454  }
458  ESemaphorePublic(Long initcnt, Bool bInit = True)
459  : m_semid(0)
460  {
461  if (bInit)
462  init(initcnt);
463  }
466  {
467  destroy();
468  }
469 
472  Void init(Long initialCount);
474  Void destroy();
475 
478  Int &semIndex();
479 
482  Void attach(Int semid);
484  Void detach();
485 
486 protected:
488  Int &nextIndex();
489  ESemaphoreData &getData();
491 
492 private:
493  Int m_semid;
494 };
495 
497 // Private Read/Write Lock Classes
499 
500 DECLARE_ERROR_ADVANCED2(ERWLockError_LockAttrInitFailed);
501 DECLARE_ERROR_ADVANCED2(ERWLockError_LockInitFailed);
502 
503 class ERDLock;
504 class EWRLock;
505 
507 class ERWLock
508 {
509  friend ERDLock;
510  friend EWRLock;
511 
512 public:
514  ERWLock();
516  ~ERWLock();
517 
518 protected:
520  enum ReadWrite
521  {
522  Read,
523  Write
524  };
525 
526  Bool enter( ReadWrite rw, Bool wait );
527  Void leave();
529 
530 private:
531  pthread_rwlock_t m_rwlock;
532 };
533 
535 class ERDLock
536 {
537 public:
541  ERDLock( ERWLock & rwlock, Bool acq = true )
542  : m_rwlock( rwlock ),
543  m_locked( false )
544  {
545  if (acq)
546  acquire();
547  }
550  {
551  if (m_locked)
552  m_rwlock.leave();
553  }
554 
558  Bool acquire( Bool wait = true )
559  {
560  return m_locked = m_rwlock.enter( ERWLock::Read, wait );
561  }
564  Bool isLocked() { return m_locked; }
565 
566 private:
567  ERDLock();
568 
569  ERWLock &m_rwlock;
570  Bool m_locked;
571 };
572 
574 class EWRLock
575 {
576 public:
580  EWRLock( ERWLock & rwlock, Bool acq = true )
581  : m_rwlock( rwlock ),
582  m_locked( false )
583  {
584  if (acq)
585  acquire();
586  }
589  {
590  if (m_locked)
591  m_rwlock.leave();
592  }
593 
597  Bool acquire( Bool wait = true )
598  {
599  return m_locked = m_rwlock.enter( ERWLock::Write, wait );
600  }
603  Bool isLocked() { return m_locked; }
604 
605 private:
606  EWRLock();
607 
608  ERWLock &m_rwlock;
609  Bool m_locked;
610 };
611 
614 
616 class EEvent
617 {
618 public:
621  EEvent( bool state = false );
623  ~EEvent();
624 
626  Void reset();
628  Void set();
633  Bool wait( int ms = -1 );
636  Bool isSet() { return wait(0); }
637 
638 private:
639  void closepipe();
640 
641  int m_pipefd[2];
642  char m_buf[1];
643 };
644 
647 
648 #endif // #define __esynch_h_included
ESemaphoreData::shared
Bool & shared()
Retrieves a reference indicating if this is a shared semaphore (public).
Definition: esynch.h:314
EMutexData::init
Void init(Bool shared)
Initializes the mutex data.
ERDLock::~ERDLock
~ERDLock()
Class destructor.
Definition: esynch.h:549
DECLARE_ERROR
#define DECLARE_ERROR(__e__)
Declares exception class derived from EError with no constructor parameters.
Definition: eerror.h:53
ESemaphoreBase::ESemaphoreBase
ESemaphoreBase()
Default constructor.
Definition: esynch.h:335
EMutexLock::EMutexLock
EMutexLock(EMutexData &mtx, Bool acquire=True)
Class constructor.
Definition: esynch.h:139
eerror.h
Defines base class for exceptions and declaration helper macros.
ESemaphoreData
Contains the data associated with a public or private semaphore.
Definition: esynch.h:268
EWRLock::acquire
Bool acquire(Bool wait=true)
Acquires the lock.
Definition: esynch.h:597
ESemaphoreData::init
Void init()
Initializes the semaphore data.
Definition: esynch.cpp:443
EMutexPublic::detach
Void detach()
Detaches from the public mutex object.
Definition: esynch.cpp:432
ESemaphoreData::destroy
Void destroy()
Destroys the semaphore data.
Definition: esynch.cpp:455
ERDLock::acquire
Bool acquire(Bool wait=true)
Acquires the lock.
Definition: esynch.h:558
EEvent
An object that can be waited on to be set in another thread.
Definition: esynch.h:616
EMutexPublic::~EMutexPublic
~EMutexPublic()
Class destructor.
Definition: esynch.h:235
EMutexPublic::destroy
Void destroy()
Destroys/releases the mutex object.
Definition: esynch.cpp:408
True
#define True
True.
Definition: ebase.h:25
ESemaphorePublic::ESemaphorePublic
ESemaphorePublic()
Default constructor.
Definition: esynch.h:451
EMutexPrivate::EMutexPrivate
EMutexPrivate(Bool bInit=True)
Class constructor.
Definition: esynch.h:180
EMutexData::initialized
Bool initialized()
Retrieves object initialization status.
Definition: esynch.h:93
ebase.h
Macros for various standard C library functions and standard includes.
ESemaphorePrivate::ESemaphorePrivate
ESemaphorePrivate(Long initcnt=0, Bool bInit=True)
Class constructor.
Definition: esynch.h:388
EMutexLock::~EMutexLock
~EMutexLock()
Class destructor. Unlocks the mutex if locked.
Definition: esynch.h:146
ESemaphoreBase::~ESemaphoreBase
~ESemaphoreBase()
Class desctructor.
Definition: esynch.h:337
EMutexPrivate::~EMutexPrivate
~EMutexPrivate()
Class destructor.
Definition: esynch.h:187
EMutexPublic::attach
Void attach(Int mutexid)
Associates this public mutex object with the mutex ID located in shared memory.
Definition: esynch.cpp:425
ESemaphorePublic::detach
Void detach()
Detaches from the semaphore data.
Definition: esynch.cpp:569
EMutexPrivate
A private mutex (the mutex data is allocated from either the heap or stack).
Definition: esynch.h:175
ESemaphorePrivate::init
Void init(Long initcnt)
Initializes the data associated with the semaphore.
Definition: esynch.h:402
EEvent::reset
Void reset()
Resets the event state.
Definition: esynch.cpp:679
ESemaphoreData::initialized
Bool initialized()
Retrieves the initialization status.
Definition: esynch.h:311
ESemaphorePublic::~ESemaphorePublic
~ESemaphorePublic()
Class destructor.
Definition: esynch.h:465
EThreadQueueMode::ReadWrite
Allows read or write access.
ESemaphorePublic::attach
Void attach(Int semid)
Attaches this object to the semaphore data associated with the semaphore ID.
Definition: esynch.cpp:562
EWRLock::isLocked
Bool isLocked()
Retrieves the lock status.
Definition: esynch.h:603
ESemaphoreBase::Decrement
Bool Decrement(Bool wait=True)
Decrements the semaphore value.
Definition: esynch.h:348
ESemaphoreBase::initialized
Bool initialized()
Indicates the initialization status for this object.
Definition: esynch.h:355
ESemaphorePublic
Represents a public semaphore, the semaphore data is located in shared memory.
Definition: esynch.h:446
ERWLock
Encapsulates a read-write lock object.
Definition: esynch.h:507
EMutexPublic
A public mutex (the mutex data is located in shared memory).
Definition: esynch.h:223
ESemaphoreBase::shared
Bool & shared()
Indicates if this object is to be shared between processes.
Definition: esynch.h:358
EMutexPublic::mutexId
Int mutexId()
Retrieves the mutex ID associated with this public mutex.
Definition: esynch.h:253
EEvent::wait
Bool wait(int ms=-1)
Waits for the event to be set.
Definition: esynch.cpp:684
EEvent::EEvent
EEvent(bool state=false)
Class constructor.
Definition: esynch.cpp:652
False
#define False
False.
Definition: ebase.h:27
EWRLock::~EWRLock
~EWRLock()
Class destructor.
Definition: esynch.h:588
ESemaphorePrivate::destroy
Void destroy()
Destroys the data associated with the semaphore.
Definition: esynch.h:404
ESemaphoreData::ESemaphoreData
ESemaphoreData(Long initcnt, Bool shared)
Class constructor.
Definition: esynch.h:282
ERWLock::ERWLock
ERWLock()
Default constructor.
Definition: esynch.cpp:596
ERWLock::~ERWLock
~ERWLock()
Class destructor.
Definition: esynch.cpp:615
ESemaphoreData::~ESemaphoreData
~ESemaphoreData()
Class destructor.
Definition: esynch.h:290
ERDLock
Request a read lock for the specified read-write lock object.
Definition: esynch.h:535
ESemaphorePrivate
Represents a private semaphore, the semaphore data is allocated from either the stack or heap.
Definition: esynch.h:382
DECLARE_ERROR_ADVANCED
#define DECLARE_ERROR_ADVANCED(__e__)
Declares exception class derived from EError with no constructor parameters and developer defined con...
Definition: eerror.h:59
ESemaphoreBase::Increment
Bool Increment()
Increments the semaphore value.
Definition: esynch.h:351
ESemaphoreData::Increment
Bool Increment()
Increments teh semaphore.
Definition: esynch.cpp:494
EMutexData::mutex
Long & mutex()
Retrieves the underlying mutex object.
Definition: esynch.h:107
ESemaphoreBase::destroy
virtual Void destroy()=0
Destroys/releases the semaphore data. This method must be overloaded in a derived class.
ESemaphoreData::Decrement
Bool Decrement(Bool wait=True)
Decrements the semaphore.
Definition: esynch.cpp:469
ESemaphoreData::ESemaphoreData
ESemaphoreData()
Default constructor.
Definition: esynch.h:272
EWRLock
Request a write lock for the specified read-write lock object.
Definition: esynch.h:574
EMutexPublic::init
Void init()
Allocates and initializes the mutex object.
Definition: esynch.cpp:399
ESemaphoreData::initialCount
Long & initialCount()
Retrieves the initial count of the semaphore.
Definition: esynch.h:317
ERDLock::ERDLock
ERDLock(ERWLock &rwlock, Bool acq=true)
Class constructor.
Definition: esynch.h:541
ESemaphoreBase::init
virtual Void init(Long initcnt)=0
Initializes the semaphore data. This method must be overloaded in a derived class.
EMutexData::destroy
Void destroy()
Destroyes the mutex data.
EEvent::isSet
Bool isSet()
Determines if the event has been set.
Definition: esynch.h:636
EMutexLock::acquire
Bool acquire(Bool wait=True)
Manually acquires a lock on the mutex.
Definition: esynch.h:155
ESemaphorePublic::destroy
Void destroy()
Destroys the data associated with the semaphore.
Definition: esynch.cpp:534
EEvent::set
Void set()
Sets the event.
Definition: esynch.cpp:671
EWRLock::EWRLock
EWRLock(ERWLock &rwlock, Bool acq=true)
Class constructor.
Definition: esynch.h:580
ERDLock::isLocked
Bool isLocked()
Retrieves the lock status.
Definition: esynch.h:564
EMutexPublic::EMutexPublic
EMutexPublic(Bool bInit=True)
Default constructor.
Definition: esynch.h:228
DECLARE_ERROR_ADVANCED2
DECLARE_ERROR_ADVANCED2(ERWLockError_LockAttrInitFailed)
ESemaphoreBase
Contains the base functionality for a semaphore.
Definition: esynch.h:331
ESynchObjects
Used internally by EpcTools for managing access to public (shared memory) objects.
Definition: esynch2.h:41
ESemaphorePrivate::~ESemaphorePrivate
~ESemaphorePrivate()
Class destructor.
Definition: esynch.h:395
estring.h
Encapsulates and extends a std::string object.
EEvent::~EEvent
~EEvent()
Class destructor.
Definition: esynch.cpp:666
ESemaphorePublic::semIndex
Int & semIndex()
Retrieves the semaphore data index.
Definition: esynch.cpp:555
EMutexPrivate::init
Void init()
Definition: esynch.h:195
EMutexLock
Acquires and holds a lock on the specified mutex.
Definition: esynch.h:133
ESemaphorePublic::ESemaphorePublic
ESemaphorePublic(Long initcnt, Bool bInit=True)
Class constructor.
Definition: esynch.h:458
ESemaphorePublic::init
Void init(Long initialCount)
Initializes the data associated with the semaphore.
Definition: esynch.cpp:522
EMutexData::~EMutexData
~EMutexData()
Class destructor.
Definition: esynch.h:80
ESemaphoreData::currCount
Long currCount()
Retrieves the current semaphore count.
Definition: esynch.h:320
ESemaphoreBase::initialCount
Long & initialCount()
Retrieves the initial semaphore value.
Definition: esynch.h:361
EMutexData
Contains the data associated with a public or private mutex.
Definition: esynch.h:72
ESemaphoreBase::currCount
Long currCount()
Retrieves the current semaphore value.
Definition: esynch.h:364