1+ #include " scheduler.h"
2+
3+ Scheduler::Scheduler ()
4+ {
5+ }
6+
7+ Scheduler::~Scheduler ()
8+ {
9+ stopAllTimers ();
10+ }
11+
12+ void Scheduler::stopAllTimers ()
13+ {
14+ for (auto &future : futures)
15+ {
16+ if (future.valid ())
17+ {
18+ future.wait (); // Wait for all threads to finish
19+ }
20+ }
21+ }
22+
23+ void Scheduler::startRetransmissionTimer (int packetID, Callback callback, std::shared_ptr<std::promise<bool >> ackPromise)
24+ {
25+ // Promise to manage the lifecycle of the thread itself
26+ std::promise<void > threadCompletionPromise;
27+
28+ // Future object to track the thread's completion
29+ std::future<void > future = threadCompletionPromise.get_future ();
30+
31+ // Store the future to ensure we can wait for the thread to finish later
32+ futures.push_back (std::move (future));
33+
34+ // Start a new thread for handling retransmission and ACK wait
35+ std::thread ([this , packetID, callback, threadCompletionPromise = std::move (threadCompletionPromise), ackPromise]() mutable
36+ {
37+ int retryCount = 0 ;
38+
39+ {
40+ // Lock the mutex to synchronize access to shared data (ackReceived)
41+ std::unique_lock<std::mutex> lock (mutex);
42+
43+ // Wait for an ACK or timeout
44+ if (cv.wait_for (lock, MAX_ACK_TIMEOUT, [this , packetID]()
45+ { return ackReceived[packetID]; }))
46+ {
47+ // ACK received within the timeout period
48+ std::cout << " ACK received for packet ID: " << packetID << std::endl;
49+ clearPacketData (packetID); // Clear packet data
50+
51+ // Set both promises to indicate success and thread completion
52+ threadCompletionPromise.set_value ();
53+ ackPromise->set_value (true ); // ACK was received, set to true
54+ return ; // Exit the thread
55+ }
56+ else
57+ {
58+ // Timeout occurred, retransmit the packet
59+ retryCounts[packetID]++;
60+ retryCount = retryCounts[packetID];
61+ std::cout << " Timeout! Retransmitting packet ID: " << packetID << std::endl;
62+ }
63+ }
64+
65+ // Call the callback function with the updated retry count
66+ callback (retryCount);
67+
68+ // Set the promise to indicate the thread has finished
69+ threadCompletionPromise.set_value ();
70+ })
71+ .detach (); // Detach the thread to allow it to run independently
72+ }
73+
74+ void Scheduler::receiveACK (int packetID)
75+ {
76+ std::unique_lock<std::mutex> lock (mutex);
77+ ackReceived[packetID] = true ;
78+ cv.notify_all (); // Notify all waiting threads
79+ }
80+
81+ void Scheduler::clearPacketData (int packetID)
82+ {
83+ ackReceived.erase (packetID);
84+ retryCounts.erase (packetID);
85+ }
0 commit comments