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