int main() { JTCInitialize boot_jtc; try { // // TEST: Verify notify() or notifyAll() occur when wait() is // called. // JTCHandleT<TestThread> t = new TestThread; t -> start(); // // Wait for the thread to start // t -> wait_start(); // // Notify the thread. Note that the monitor cannot be notified // until the lock is obtained which should mean that the // monitor is already waiting. // { JTCSynchronized sync(*t); t -> notify(); } while (t -> isAlive()) { try { t -> join(); } catch(const JTCInterruptedException&) { } } // // TEST: Verify that one call to notify() will take one // thread (not two!) // JTCMonitor mon; JTCHandleT<WaitThread> t1 = new WaitThread(mon); JTCHandleT<WaitThread> t2 = new WaitThread(mon); t1 -> start(); t2 -> start(); // // Wait until the threads enter wait(). // JTCThread::sleep(1000); { JTCSynchronized sync(mon); mon.notify(); } // // Sleep a second. Either t1 or t2 might can stop -- but not // both. // JTCThread::sleep(1000); assert((t1 -> isAlive() && !t2 -> isAlive()) || (t2 -> isAlive() && !t1 -> isAlive())); { JTCSynchronized sync(mon); mon.notify(); } while (t1 -> isAlive() || t2 -> isAlive()) { try { t1 -> join(); } catch(const JTCInterruptedException&) { } } while (t2 -> isAlive()) { try { t2 -> join(); } catch(const JTCInterruptedException&) { } } // // TEST: Verify that two calls to notify() will take two // threads. // t1 = new WaitThread(mon); t2 = new WaitThread(mon); t1 -> start(); t2 -> start(); // // Wait until the threads enter wait(). // JTCThread::sleep(1000); { JTCSynchronized sync(mon); mon.notify(); mon.notify(); } while (t1 -> isAlive()) { try { t1 -> join(); } catch(const JTCInterruptedException&) { } } while (t2 -> isAlive()) { try { t2 -> join(); } catch(const JTCInterruptedException&) { } } // // TEST: Verify that a call to notifyAll() will take two // threads. // t1 = new WaitThread(mon); t2 = new WaitThread(mon); t1 -> start(); t2 -> start(); // // Wait until the threads enter wait(). // JTCThread::sleep(1000); { JTCSynchronized sync(mon); mon.notifyAll(); } while (t1 -> isAlive()) { try { t1 -> join(); } catch(const JTCInterruptedException&) { } } while (t2 -> isAlive()) { try { t2 -> join(); } catch(const JTCInterruptedException&) { } } // // TEST: Verify that a call to notifyAll() actually wakes both // threads. // int count = 1000; JTCHandleT<WaitThread2> wt1 = new WaitThread2(mon, count); JTCHandleT<WaitThread2> wt2 = new WaitThread2(mon, count); wt1 -> start(); wt2 -> start(); // // Wait until the threads enter wait(). // JTCThread::sleep(1000); while (count > 0) { JTCSynchronized sync(mon); wt1 -> consume(); wt2 -> consume(); mon.notifyAll(); --count; } while (wt1 -> isAlive()) { try { wt1 -> join(); } catch(const JTCInterruptedException&) { } } while (wt2 -> isAlive()) { try { wt2 -> join(); } catch(const JTCInterruptedException&) { } } } catch(const JTCException& e) { cout << "Test failed: " << e.getMessage() << endl; return EXIT_FAILURE; } cout << "Test successful." << endl; return EXIT_SUCCESS; }
bool CTunnelingConnection::HandleTunnelRequest(unsigned char* buffer, int len, CCemi_L_Data_Frame &frame) { JTCSynchronized s(*this); CTunnelingRequest req(buffer); if(req.GetChannelId() != _state._channelid){ //error LOG_ERROR("[Received] [BUS] CEMI frame with invalid channel id. [ignored]"); return false; } if(req.GetSequenceNumber() == _state._recv_sequence || req.GetSequenceNumber() + 1 == _state._recv_sequence) { if(req.GetSequenceNumber() == _state._recv_sequence){ _num_out_of_sync_pkts = 0; const CCemi_L_Data_Frame& tmpfrm = req.GetcEMI(); LOG_DEBUG("[Received] [BUS] [Tunnel request] Sequence: %d Dest Address: %s",req.GetSequenceNumber(), tmpfrm.GetDestAddress().ToString().GetBuffer()); }else{ LOG_ERROR("[Received] [BUS] [Tunnel request] Packet has invalid sequence number (%d). [sending ack but ignoring frame]",req.GetSequenceNumber()); } unsigned char buf[20]; CTunnelingAck ack(req.GetChannelId(),req.GetSequenceNumber(),E_NO_ERROR); ack.FillBuffer(buf,20); LOG_DEBUG("[Send] [BUS] [Tunnel Ack] Sequence: %d",req.GetSequenceNumber()); _data_sock.SendTo(buf,ack.GetTotalSize(),_device_data_address,_device_data_port); }else{ _num_out_of_sync_pkts++; //we have many pkts out of sync consecutively if(_num_out_of_sync_pkts > 3){ //we are totally out of sync. reconnect. LOG_ERROR("[Received] [BUS] [Tunnel request] Packet has invalid sequence number (%d). reconnecting is 3 seconds.",req.GetSequenceNumber()); Reconnect(); } } if(req.GetSequenceNumber() != _state._recv_sequence) { LOG_ERROR("[Received] [BUS] [Tunnel request] Packet has invalid sequence number (%d). [ignoring]",req.GetSequenceNumber()); return false; } ++_state._recv_sequence; unsigned char mc = req.GetcEMI().GetMessageCode(); //Data indication if(mc == L_DATA_IND || mc == L_BUSMON_IND) { //data indication or bus monitor indication should be processed frame = req.GetcEMI(); } //Data confirmation else if (mc == L_DATA_CON) { if(req.GetcEMI().IsPositiveConfirmation()){ //positive confirmation was received frame = req.GetcEMI(); LOG_DEBUG("[Received] [BUS] [Positive confirmation] Sequence: %d", _state._recv_sequence); map<int,JTCMonitor*>::iterator it = _waiting_for_confirms.find(_state._recv_sequence); if(it != _waiting_for_confirms.end()){ JTCMonitor* monitor = it->second; JTCSynchronized s(*monitor); _waiting_for_confirms.erase(_state._recv_sequence); monitor->notify(); } return true; } else { LOG_ERROR("[Received] [BUS] [Not supported message control field in cEMI frame (negative confirmation)]"); map<int,JTCMonitor*>::iterator it = _waiting_for_confirms.find(_state._recv_sequence); if(it != _waiting_for_confirms.end()){ JTCMonitor* monitor = it->second; JTCSynchronized s(*monitor); _waiting_for_confirms.erase(_state._recv_sequence); monitor->notify(); } return false; } }else{ LOG_ERROR("[Received] [BUS] [Not supported message control field in cEMI frame]"); } return true; }