From 9a66515b0cfb41d7c05d6b8690ac6a87fa2257f5 Mon Sep 17 00:00:00 2001 From: Toby Gray Date: Thu, 26 Aug 2010 17:40:59 +0100 Subject: [PATCH] Moving semaphore code to inside raw_channel so that clients don't have to care about it. --- src/m_raw_channel.cc | 26 +++++++++++++++++++++++++- src/m_raw_channel.h | 28 ++++++++++++++++------------ tools/brawchannel.cc | 49 ++++--------------------------------------------- 3 files changed, 45 insertions(+), 58 deletions(-) diff --git a/src/m_raw_channel.cc b/src/m_raw_channel.cc index 04c92db7..378b86cd 100644 --- a/src/m_raw_channel.cc +++ b/src/m_raw_channel.cc @@ -21,6 +21,7 @@ */ #include "m_raw_channel.h" +#include "semaphore.h" #include "data.h" #include "protocol.h" #include "protostructs.h" @@ -52,14 +53,36 @@ RawChannel::RawChannel(Controller &con, RawChannelDataCallback& callback) , m_callback(callback) , m_sendBuffer(0) , m_zeroRegistered(false) + , m_mutex_valid(false) + , m_cv_valid(false) + , m_semaphore(NULL) { m_sendBuffer = new unsigned char[MAX_PACKET_SIZE]; + + // Create the thread synchronization objects + if( pthread_mutex_init(&m_mutex, NULL) ) { + throw Barry::Error("Failed to create mutex"); + } + m_mutex_valid = true; + if( pthread_cond_init(&m_cv, NULL) ) { + throw Barry::Error("Failed to create condvar"); + } + m_cv_valid = true; + m_semaphore = new semaphore(m_mutex, m_cv); } RawChannel::~RawChannel() { UnregisterZeroSocketInterest(); delete[] m_sendBuffer; + + if( m_mutex_valid ) { + pthread_mutex_destroy(&m_mutex); + } + if( m_cv_valid ) { + pthread_cond_destroy(&m_cv); + } + delete m_semaphore; } void RawChannel::OnOpen() @@ -91,6 +114,7 @@ void RawChannel::Send(Data& data, int timeout) Data toSend(m_sendBuffer, packetSize); m_socket->Send(toSend, timeout); + m_semaphore->WaitForSignal(); } size_t RawChannel::MaximumSendSize() @@ -107,7 +131,7 @@ void RawChannel::HandleReceivedData(Data& data) switch( btohs(packet->command) ) { case SB_COMMAND_SEQUENCE_HANDSHAKE: - m_callback.DataSendAck(); + m_semaphore->Signal(); break; case SB_COMMAND_CLOSE_SOCKET: case SB_COMMAND_REMOTE_CLOSE_SOCKET: diff --git a/src/m_raw_channel.h b/src/m_raw_channel.h index 913966f5..41317f0d 100644 --- a/src/m_raw_channel.h +++ b/src/m_raw_channel.h @@ -28,9 +28,12 @@ #include "socket.h" #include +#include namespace Barry { +class semaphore; + namespace Mode { // Callback from the raw channel. @@ -38,8 +41,6 @@ namespace Mode { class BXEXPORT RawChannelDataCallback { public: - // Called when data has been sent on the channel - virtual void DataSendAck() = 0; // Called when data has been received on the channel virtual void DataReceived(Data& data) = 0; // Called when the channel has an error @@ -65,7 +66,14 @@ public: /// class BXEXPORT RawChannel : public Mode { -private: + // Mutex for signalling between read and write threads + pthread_mutex_t m_mutex; + bool m_mutex_valid; + // Condvar for signalling between read and write threads + pthread_cond_t m_cv; + bool m_cv_valid; + + semaphore* m_semaphore; RawChannelDataCallback& m_callback; unsigned char *m_sendBuffer; bool m_zeroRegistered; @@ -80,16 +88,16 @@ public: ////////////////////////////////// // Raw channel mode specific methods - // Send some data on the raw channel + // Send some data on the raw channel. // Will throw a Barry::Error if data is longer than // MaximumPacketContentsSize or a Barry::Usb::Error if there // is an underlying USB error. - // - // Before calling send again it's advisable to wait - // for the DataSendAck callback to occur. If Send is called - // again before the callback then data loss is very likely to occur. void Send(Data& data, int timeout = -1); + // Returns the maximum quantity of data which + // can be sent + size_t MaximumSendSize(); + // Not intended for use by users of this class. // Instead data received will come in via the // RawChannelDataCallback::DataReceived callback. @@ -99,10 +107,6 @@ public: // This method is called by the internals of // Barry when setting up a connection. void OnOpen(); - - // Returns the maximum quantity of data which - // can be sent - size_t MaximumSendSize(); }; }} // namespace Barry::Mode diff --git a/tools/brawchannel.cc b/tools/brawchannel.cc index 95a94a19..45e15aa8 100644 --- a/tools/brawchannel.cc +++ b/tools/brawchannel.cc @@ -23,7 +23,6 @@ #include -#include #include #include #include @@ -60,20 +59,17 @@ class CallbackHandler : public Barry::Mode::RawChannelDataCallback private: volatile bool* m_continuePtr; bool m_verbose; - semaphore& m_semaphore; public: - CallbackHandler(volatile bool& keepGoing, bool verbose, semaphore& semaphore) + CallbackHandler(volatile bool& keepGoing, bool verbose) : m_continuePtr(&keepGoing) , m_verbose(verbose) - , m_semaphore(semaphore) { } public: // From RawChannelDataCallback virtual void DataReceived(Data& data); - virtual void DataSendAck(); virtual void ChannelError(string msg); virtual void ChannelClose(); }; @@ -106,11 +102,6 @@ void CallbackHandler::DataReceived(Data& data) } } -void CallbackHandler::DataSendAck() -{ - m_semaphore.Signal(); -} - void CallbackHandler::ChannelError(string msg) { cerr << "CallbackHandler: Received error: " << msg << endl; @@ -120,7 +111,6 @@ void CallbackHandler::ChannelError(string msg) void CallbackHandler::ChannelClose() { *m_continuePtr = false; - m_semaphore.Signal(); } // Class which extends the functionality of SocketRoutingQueue to add @@ -144,7 +134,6 @@ protected: *q->m_continuePtr ) { cerr << "Error in ReadThread: " << msg << endl; *q->m_continuePtr = false; - q->m_semaphore.Signal(); } } return 0; @@ -154,13 +143,11 @@ protected: volatile bool* m_continuePtr; volatile bool m_runningThread; pthread_t m_usb_read_thread; - semaphore& m_semaphore; public: - ErrorHandlingSocketRoutingQueue(volatile bool& continuePtr, semaphore& semaphore) + ErrorHandlingSocketRoutingQueue(volatile bool& continuePtr) : m_socketRoutingQueue() , m_continuePtr(&continuePtr) , m_runningThread(false) - , m_semaphore(semaphore) { // Nothing to do } @@ -251,12 +238,6 @@ int main(int argc, char *argv[]) // Buffer to hold data read in from STDIN before sending it // to the BlackBerry. unsigned char* buf = NULL; - // Mutex for signalling between read and write threads - pthread_mutex_t mutex; - bool mutex_valid = false; - // Condvar for signalling between read and write threads - pthread_cond_t cv; - bool cv_valid = false; try { uint32_t pin = 0; bool data_dump = false; @@ -346,26 +327,14 @@ int main(int argc, char *argv[]) volatile bool running = true; - // Create the thread synchronization objects - if( pthread_mutex_init(&mutex, NULL) ) { - throw Barry::Error("Failed to create mutex"); - } - mutex_valid = true; - if( pthread_cond_init(&cv, NULL) ) { - throw Barry::Error("Failed to create condvar"); - } - cv_valid = true; - - semaphore sem(mutex, cv); - // Create the thing which will write onto stdout // and perform other callback duties. - CallbackHandler callbackHandler(running, data_dump, sem); + CallbackHandler callbackHandler(running, data_dump); // Start a thread to handle any data arriving from // the BlackBerry. auto_ptr router; - router.reset(new ErrorHandlingSocketRoutingQueue(running, sem)); + router.reset(new ErrorHandlingSocketRoutingQueue(running)); router->SpinoffReadThread(); // Create our controller object @@ -421,9 +390,6 @@ int main(int argc, char *argv[]) cerr.setf(ios::dec, ios::basefield); cerr << "Sent " << ios::dec << haveRead << " bytes stdin->USB\n"; } - // Wait for the write to be completed before reading - // the next data to send. - sem.WaitForSignal(); } else if( haveRead < 0 ) { running = false; @@ -446,13 +412,6 @@ int main(int argc, char *argv[]) delete[] buf; - if( mutex_valid ) { - pthread_mutex_destroy(&mutex); - } - if( cv_valid ) { - pthread_cond_destroy(&cv); - } - return 0; } -- 2.11.4.GIT