1 //-----------------------------------------------------------------------------
2 //
3 // WaitImpl.cpp
4 //
5 // POSIX implementation of an abstract base class for objects we
6 // want to be able to wait for.
7 //
8 // Copyright (c) 2010 Mal Lansell <mal@lansell.org>
9 // All rights reserved.
10 //
11 // SOFTWARE NOTICE AND LICENSE
12 //
13 // This file is part of OpenZWave.
14 //
15 // OpenZWave is free software: you can redistribute it and/or modify
16 // it under the terms of the GNU Lesser General Public License as published
17 // by the Free Software Foundation, either version 3 of the License,
18 // or (at your option) any later version.
19 //
20 // OpenZWave is distributed in the hope that it will be useful,
21 // but WITHOUT ANY WARRANTY; without even the implied warranty of
22 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 // GNU Lesser General Public License for more details.
24 //
25 // You should have received a copy of the GNU Lesser General Public License
26 // along with OpenZWave. If not, see <http://www.gnu.org/licenses/>.
27 //
28 //-----------------------------------------------------------------------------
29 #include "Defs.h"
30 #include "platform/Wait.h"
31 #include "WaitImpl.h"
32
33 #include <stdio.h>
34 #include <errno.h>
35
36 using namespace OpenZWave;
37
38 //-----------------------------------------------------------------------------
39 // <WaitImpl::WaitImpl>
40 // Constructor
41 //-----------------------------------------------------------------------------
WaitImpl(Wait * _owner)42 WaitImpl::WaitImpl
43 (
44 Wait* _owner
45 ):
46 m_owner( _owner )
47 {
48 pthread_mutexattr_t ma;
49 pthread_mutexattr_init ( &ma );
50 pthread_mutexattr_settype( &ma, PTHREAD_MUTEX_RECURSIVE );
51 pthread_mutex_init( &m_criticalSection, &ma );
52 pthread_mutexattr_destroy( &ma );
53 }
54
55 //-----------------------------------------------------------------------------
56 // <WaitImpl::~WaitImpl>
57 // Destructor
58 //-----------------------------------------------------------------------------
~WaitImpl()59 WaitImpl::~WaitImpl
60 (
61 )
62 {
63 pthread_mutex_destroy( &m_criticalSection );
64 }
65
66 //-----------------------------------------------------------------------------
67 // <WaitImpl::AddWatcher>
68 // Add a watcher to our object.
69 //-----------------------------------------------------------------------------
AddWatcher(Wait::pfnWaitNotification_t _callback,void * _context)70 void WaitImpl::AddWatcher
71 (
72 Wait::pfnWaitNotification_t _callback,
73 void* _context
74 )
75 {
76 // Add the watcher to our list
77 Watcher watcher;
78 watcher.m_callback = _callback;
79 watcher.m_context = _context;
80
81 if( pthread_mutex_lock( &m_criticalSection ) != 0 )
82 {
83 fprintf(stderr, "WaitImpl::AddWatcher lock error %d\n", errno );
84 assert( 0 );
85 }
86 m_watchers.push_back( watcher );
87 if( pthread_mutex_unlock( &m_criticalSection ) != 0 )
88 {
89 fprintf(stderr, "WaitImpl::AddWatcher unlock error %d\n", errno );
90 assert( 0 );
91 }
92
93 // If the object is already in a signalled state, notify the watcher immediately
94 if( m_owner->IsSignalled() )
95 {
96 _callback( _context );
97 }
98 }
99
100 //-----------------------------------------------------------------------------
101 // <WaitImpl::RemoveWatcher>
102 // Remove a watcher from our object.
103 //-----------------------------------------------------------------------------
RemoveWatcher(Wait::pfnWaitNotification_t _callback,void * _context)104 bool WaitImpl::RemoveWatcher
105 (
106 Wait::pfnWaitNotification_t _callback,
107 void* _context
108 )
109 {
110 bool res = false;
111
112 if( pthread_mutex_lock( &m_criticalSection ) != 0 )
113 {
114 fprintf(stderr, "WaitImpl::RemoveWatcher lock error %d\n", errno );
115 assert( 0 );
116 }
117
118 for( list<Watcher>::iterator it=m_watchers.begin(); it!=m_watchers.end(); ++it )
119 {
120 Watcher const& watcher = *it;
121 if( ( watcher.m_callback == _callback ) && ( watcher.m_context == _context ) )
122 {
123 m_watchers.erase( it );
124 res = true;
125 break;
126 }
127 }
128
129 if( pthread_mutex_unlock( &m_criticalSection ) != 0 )
130 {
131 fprintf(stderr, "WaitImpl::RemoveWatcher unlock error %d\n", errno );
132 assert( 0 );
133 }
134 return res;
135 }
136
137 //-----------------------------------------------------------------------------
138 // <WaitImpl::Notify>
139 // Notify all the watchers that the object has become signalled
140 //-----------------------------------------------------------------------------
Notify()141 void WaitImpl::Notify
142 (
143 )
144 {
145 if( pthread_mutex_lock( &m_criticalSection ) != 0 )
146 {
147 fprintf(stderr, "WaitImpl::Notify lock error %d\n", errno );
148 assert( 0 );
149 }
150 for( list<Watcher>::iterator it=m_watchers.begin(); it!=m_watchers.end(); ++it )
151 {
152 Watcher const& watcher = *it;
153 watcher.m_callback( watcher.m_context );
154 }
155 if( pthread_mutex_unlock( &m_criticalSection ) != 0 )
156 {
157 fprintf(stderr, "WaitImpl::Notify unlock error %d\n", errno );
158 assert( 0 );
159 }
160 }
161