Single lane bridge Synchronization using semaphores - c++

I am trying to implement Single Lane Bridge synchronization problem.
At a time, cars can go in one direction only and also the capacity of the bridge is 5.I have come up with something below.
int curr_direction = -1;
//curr_direction values can be -1,1 and 2.-1 means bridge is empty
int cars_count = 0;
HANDLE sem_bridgempty;//To keep track whether the bridge is empty or not
HANDLE sem_bridgecount; //To keep track of count of cars on bridge
HANDLE mut_mutex;//For exclusive access
unsigned WINAPI enter(void *param)
{
int direction = *((int *)param);
WaitForSingleObject(mut_mutex,INFINITE);
if (curr_direction == -1)
curr_direction = direction;
ReleaseMutex(mut_mutex);
WaitForSingleObject(sem_bridgecount, INFINITE);//Wait if more than 5 cars
WaitForSingleObject(mut_mutex, INFINITE);
if (direction == curr_direction)
{
cars_count++;
std::cout << "Car with direction " << direction << " entered " <<
GetCurrentThreadId() << std::endl;
ReleaseMutex(mut_mutex);
}
else
{
ReleaseMutex(mut_mutex);
WaitForSingleObject(sem_bridgempty, INFINITE);//Wait for bridge to be empty so other direction car can enter
WaitForSingleObject(mut_mutex,INFINITE);
curr_direction = direction;
cars_count++;
std::cout << "Car with direction " << direction << " entered " << GetCurrentThreadId() << std::endl;
ReleaseMutex(mut_mutex);
}
return 0;
}
unsigned WINAPI exit(void *param)
{
WaitForSingleObject(mut_mutex, INFINITE);
cars_count--;
std::cout << "A Car exited " << GetCurrentThreadId() << std::endl;
ReleaseSemaphore(sem_bridgecount, 1, NULL);
if (cars_count == 0)
{
curr_direction = -1;
std::cout << "Bridge is empty " << GetCurrentThreadId() <<
std::endl;
ReleaseSemaphore(sem_bridgempty, 1, NULL);
}
ReleaseMutex(mut_mutex);
return 0;
}
int main()
{
sem_bridgecount = CreateSemaphore(NULL, 5, 5, NULL);
sem_bridgempty = CreateSemaphore(NULL, 0, 1, NULL);
sem_bridge_not_empty = CreateSemaphore(NULL, 0, 2, NULL);
mut_mutex = CreateMutex(NULL, false, NULL);
The synchronization does not work.When i test this i can see cars with direction1 and 2 entering at same time.
else
{
ReleaseMutex(mut_mutex);
WaitForSingleObject(sem_bridgempty, INFINITE); //line 1
WaitForSingleObject(mut_mutex, INFINITE);//line 2
Suppose Thread1 with direction 2 is waiting for sem_bridge_empty.
When the bridge becomes empty(direction=-1), it comes at line 2.But before it acquires mut_mutex, another thread with direction = 1 calls enter and sees direction=-1 and enters.Now when control comes back at thread1, it also enters with direction=2 because it is oblivious of the fact that another thread has already entered which is of different direction.
How can i bring mut_mutex and sem_bridge_empty in sync?

your WaitForSingleObject(mut_mutex) not match ReleaseMutex(mut_mutex) count - you (in enter) 2 or 3 times call ReleaseMutex for single WaitForSingleObject this already critical bug. if (direction == curr_direction) called already outside of synchronization section - so curr_direction can be changed at any time.
correct solution - check and modify must be "atomic" operation - inside some critical section. so associate some cs with bridge, which will be guard it state. when car try enter to bridge - enter once(!) to this cs, decide are car can enter or need wait. exit cs. and if need wait - wait (of course outside cs). mutex also can be used here but use cs or SRW locks much better - because with mutex you will be every time enter kernel for synchronization. with cs - only when really need wait.
also you not take in account next situation - if (direction == curr_direction) you always enter to bridge. but what if from opposite site already waited some cars ? the side (direction) which fist enter to bridge can infinite hold it (assume infinite car stream in this direction), when another direction will be infinite wait. for solve this - need add some "traffic light" - even if carr moved in current bridge direction and exist free space on bridge - it can stop and wait, if already cars waited from opposite side.
also note how you pass parameter (direction) to thread - why by pointer but not by value ? and if this is c++ - why not encapsulate bridge logic (all it variables and synchronization objects in some struct ?
i be select next solution (with statistic):
struct Bridge : CRITICAL_SECTION
{
enum { MaxPositions = 3, MaxTransitsWhenOppositeWait = 1 };
HANDLE _hSemaphore[2];
ULONG _nWaitCount[2];
ULONG _nFreePositions, _nTransits;
LONG _direction;
//+++ statistic for test only
struct STAT {
ULONG _Exits[2];
ULONG _nWaitCount[2];
LONG _direction;
ULONG _CarsOnBridge;
} _stat[16];
ULONG _i_stat, _Exits[2], _nExits;
void CollectStat(LONG direction)
{
_Exits[direction]++;
if (!(++_nExits & 0xfff))// on every 0x1000*n exit save stat
{
if (_i_stat)
{
STAT *stat = &_stat[--_i_stat];
stat->_CarsOnBridge = MaxPositions - _nFreePositions;
stat->_direction = direction;
stat->_nWaitCount[0] = _nWaitCount[0];
stat->_nWaitCount[1] = _nWaitCount[1];
stat->_Exits[0] = _Exits[0];
stat->_Exits[1] = _Exits[1];
}
}
}
void DumpStat()
{
if (ULONG i = RTL_NUMBER_OF(_stat) - _i_stat)
{
do
{
STAT *stat = &_stat[_i_stat++];
DbgPrint("<(+%05u, -%05u) %c%u (+%u, -%u)>\n", stat->_Exits[0], stat->_Exits[1],
stat->_direction ? '-' : '+',
stat->_CarsOnBridge, stat->_nWaitCount[0], stat->_nWaitCount[1]);
} while (--i);
}
}
void InitStat()
{
RtlZeroMemory(_Exits, sizeof(_Exits)), _nExits = 0;
RtlZeroMemory(_stat, sizeof(_stat)), _i_stat = RTL_NUMBER_OF(_stat);
}
//--- statistic for test only
void Lock() { EnterCriticalSection(this); }
void Unlock() { LeaveCriticalSection(this); }
Bridge()
{
InitializeCriticalSection(this);
_hSemaphore[0] = 0, _hSemaphore[1] = 0;
_nWaitCount[0] = 0, _nWaitCount[1] = 0;
_nFreePositions = MaxPositions, _nTransits = MaxTransitsWhenOppositeWait, _direction = -1;
InitStat();
}
~Bridge()
{
DeleteCriticalSection(this);
if (_hSemaphore[1]) CloseHandle(_hSemaphore[1]);
if (_hSemaphore[0]) CloseHandle(_hSemaphore[0]);
if (_nWaitCount[0] || _nWaitCount[1] || _nFreePositions != MaxPositions)
{
__debugbreak();
}
DumpStat();
}
BOOL Create()
{
return (_hSemaphore[0] = CreateSemaphore(0, 0, MaxPositions, 0)) &&
(_hSemaphore[1] = CreateSemaphore(0, 0, MaxPositions, 0));
}
BOOL IsOppositeSideWaiting(LONG direction)
{
return _nWaitCount[1 - direction];
}
void EnterCars(LONG direction, ULONG n)
{
if (IsOppositeSideWaiting(direction))
{
_nTransits--;
}
_nFreePositions -= n;
}
void Enter(LONG direction)
{
BOOL bWait = FALSE;
Lock();
if (_direction < 0)
{
_direction = direction;
goto __m0;
}
else if (_direction == direction && _nFreePositions && _nTransits)
{
__m0:
EnterCars(direction, 1);
}
else
{
bWait = TRUE;
_nWaitCount[direction]++;
}
Unlock();
if (bWait)
{
if (WaitForSingleObject(_hSemaphore[direction], INFINITE) != WAIT_OBJECT_0)
{
__debugbreak();
}
}
}
void Exit(LONG direction)
{
if (_direction != direction)
{
__debugbreak();
}
Lock();
CollectStat(direction);
if (++_nFreePositions == MaxPositions)
{
// bridge is empty
_direction = -1, _nTransits = MaxTransitsWhenOppositeWait;
// change direction if opposite side wait
if (IsOppositeSideWaiting(direction))
{
direction = 1 - direction;
}
}
HANDLE hSemaphore = _hSemaphore[direction];
ULONG n = _nTransits ? min(_nWaitCount[direction], _nFreePositions) : 0;
if (n)
{
_direction = direction;
EnterCars(direction, n);
_nWaitCount[direction] -= n;
ReleaseSemaphore(hSemaphore, n, 0);
}
Unlock();
}
} g_Bridge;
ULONG car(LONG direction)
{
direction &= 1;// 0 or 1
WCHAR caption[16];
int i = 0x10000;// Number of transits
do
{
swprintf(caption, L"[%u] %08x", direction, GetCurrentThreadId());
//MessageBoxW(0, 0, caption, MB_OK);
SwitchToThread();// simulate wait
g_Bridge.Enter(direction);
SwitchToThread();// simulate wait
//MessageBoxW(0, 0, caption, direction ? MB_ICONWARNING : MB_ICONINFORMATION);
g_Bridge.Exit(direction);
direction = 1 - direction;// reverse direction
} while (--i);
return direction;//visible thread exit code in debug window
}
void SLBT()
{
if (g_Bridge.Create())
{
HANDLE hThreads[8], *phThread = hThreads, hThread;
ULONG n = RTL_NUMBER_OF(hThreads), m = 0;
do
{
if (hThread = CreateThread(0, PAGE_SIZE, (PTHREAD_START_ROUTINE)car, (PVOID)n, 0, 0))
{
*phThread++ = hThread, m++;
}
} while (--n);
if (m)
{
WaitForMultipleObjects(m, hThreads, TRUE, INFINITE);
do
{
CloseHandle(*--phThread);
} while (--m);
}
}
}
for check how cars go on bridge i collect some stat on every n*0x1000 exits. also note that on every exit i check direction is correct : if (_direction != direction) __debugbreak();
some stat output: (how many cars gone through bridge in every direction, how many cars now on bridge and it direction(+/-). and how many cars wait now)
<(+32768, -32768) +3 (+2, -3)>
<(+30720, -30720) -2 (+2, -3)>
<(+28672, -28672) +3 (+2, -3)>
<(+26625, -26623) +1 (+2, -5)>
<(+24576, -24576) -3 (+3, -2)>
<(+22529, -22527) +1 (+2, -5)>
<(+20480, -20480) +2 (+3, -2)>
<(+18432, -18432) +3 (+1, -3)>
<(+16385, -16383) +1 (+2, -3)>
<(+14335, -14337) -1 (+4, -2)>
<(+12288, -12288) +3 (+2, -3)>
<(+10239, -10241) -1 (+3, -2)>
<(+08192, -08192) +2 (+3, -3)>
<(+06143, -06145) -1 (+3, -2)>
<(+04096, -04096) +3 (+2, -3)>
<(+02048, -02048) +2 (+3, -3)>
also you can uncomment messageboxes and reduce Number of transits for control cars in "manual" mode
of corse also can play with MaxPositions and MaxTransitsWhenOppositeWait for example when enum { MaxPositions = 5, MaxTransitsWhenOppositeWait = 2 };
<(+32766, -32770) -1 (+7, -0)>
<(+30721, -30719) -5 (+0, -1)>
<(+28674, -28670) +1 (+0, -7)>
<(+26623, -26625) +5 (+2, -0)>
<(+24574, -24578) -1 (+7, -0)>
<(+22528, -22528) -5 (+0, -0)>
<(+20479, -20481) -3 (+2, -0)>
<(+18431, -18433) +5 (+2, -1)>
<(+16383, -16385) +5 (+2, -0)>
<(+14337, -14335) -5 (+0, -2)>
<(+12290, -12286) +1 (+0, -5)>
<(+10241, -10239) -5 (+0, -2)>
<(+08190, -08194) -1 (+7, -0)>
<(+06143, -06145) -2 (+3, -1)>
<(+04096, -04096) +5 (+0, -1)>
<(+02047, -02049) -3 (+1, -0)>

I think I'd go about this rather differently.
The way I'd see the problem would be to model real life a little more closely.
There's a bridge. There's a queue at each end of the bridge where cars await entry. There's an agent (corresponding to the flag man at the end of the bridge) that can release cars from a queue.
A car (thread) that wants to cross the bridge creates an event and puts the event into the queue for crossing the bridge in whichever direction it's going. It then sleeps on the event. When it gets to the front of the queue and the agent decides to release that car, it removes the event from the queue and signals it. The car then proceeds across the bridge. When it gets to the other end, it notifies that it's leaving the bridge by doing a ReleaseSemaphore.
Each agent waits on (I believe) three factors:
Direction == my direction
There's room on the bridge
There's at least one car in my queue
When those occur, it releases a car from its queue, then repeats.
If you want to add a little embellishment, an agent could release the remainder of its time slice when its queue is empty (or maybe only when it stays empty for more than some short period of time).
At least to me, this seems simpler to implement, and considerably more realistic. When the bridge changes direction, we don't want to just choose five random cars to let through--we always choose those that have been waiting the longest.
If we wanted to make things even more realistic, we could make it a deque instead of a queue. Emergency vehicles (ambulance, fire truck, etc.) would go to the front of the deque instead of the back. When they arrive, the timer for the vehicles moving the other direction would expire immediately (but they'd still wait for vehicles on the bridge to exit before they entered).

Related

Arduino - Measuring the time interval between one button press and release - Add Velocity to MIDI Keyboard

I hope you are doing all really well, I am trying to make a MIDI Piano Keyboard, Pretty basic I press a key the MIDI signal is send and the sounds comes.
But I want to add the velocity to the my keys, there are one contacts per key (the keyboard I am using is Fatar Keyboard).
I need to calculate the time interval between the first contact and then the second contact ( Circuit Diagram is attached below).
All the keys are in set as input pull_up
when a key is pressed it goes low … Of course
Mentioned Below is the function where I am reading the keys. what do I need to do to get the following situation done
[they are 49 keys which are arranged in to two diode matrices. There are actually 98 switches in the matrix. The reason for this is that there are two switches under each key. When a key is pressed, one of the switches closes slightly before the other one. By measuring the time of flight between the switches we can derive the velocity]
Situation 1
Key is pressed
Start Time
Time for how long its pressed
Key Released
Code
void read_keys() {
for (uint8_t key = 0; key < 49; key ++) {
digitalWrite(output_main[key], LOW); //turn off output main key
if (digitalRead(input_pullup[key]) == LOW) {
//check main input key is presses
//check with key_activated array
firstcontactdownmills = millis();
Serial.println(key);
Velocity = map(currentmills - firstcontactdownmills, 0, 256, 127, 0);
if (key_activated[key] == 0) {
//send midi on command
my_midi.sendNoteOn(key + note_offset, Velocity, 1);
main_midi.sendNoteOn(key + note_offset, Velocity, 1);
//update array
key_activated[key] = 1;
}
}
else { //if key released
//check with key_activated array
if (key_activated[key] == 1) {
//send midi off command
my_midi.sendNoteOff(key + note_offset, 0, 1);
main_midi.sendNoteOff(key + note_offset, 0, 1);
//update array
key_activated[key] = 0;
}
}
digitalWrite(output_main[key], HIGH); //turn on output main key
}
}
Circuit Diagram of the Keyboard
You can add a state variable to your keys, that keeps track of where your key is. You can then start the timer at the transition from not_pressed to half_pressed. You then evaluate the velocity at a transition from half_pressed to full_pressed.
You should also add a timeout that resets it back to unpressed in case a key press is missed.
But I am not sure if your loop will be fast enough after adding this kind of logic.
Here's an idea that assumes that if a keyboard player is holding down a key, the contact pin will stay LOW and that there will be 3 interesting state changes
First HIGH->LOW : First contact - record the current time using millis()
Second HIGH->LOW : Second contact - calculate velocity and send key on.
Third HIGH->LOW : Release contact - send key off
Since it doesn't seem possible to actually know if it's contact1 or contact2 that causes the pin to go LOW, it's very sensitive. If you start the program while holding down a key, that will cause the program to think it's the first contact - and everything after that will be messed up.
First, you need something to convert the time between two contact events into velocity. Here's a linear conversion funciton. You'll need to find the proper constants for min and max for your keyboard by measuring.
unsigned char calc_velocity(unsigned ms) {
static constexpr unsigned min = 2; // the fastest time you've measured
static constexpr unsigned max = 80; // the slowest time you've measured
static constexpr unsigned mul = 127000 / (max - min);
if(ms < min) return 127; // harder than "possible", log and recalibrate
if(ms > max) return 0; // softer than "possible", log and recalibrate
return (127000 - ((ms - min) * mul)) / 1000; // 0(min vel) - 127(max vel)
}
Then, you could create a class to keep track of the state for one key alone. It makes it easier than to have a lot of separate arrays.
// an enum for keyboard events
enum class Event { ev_nothing, ev_key_on, ev_key_off };
struct Key {
unsigned long first_contact{};
int contact_count = 0;
unsigned char velocity{};
bool contact_state = false;
// set contact state and return an Event to act upon
Event set(bool contact) { // false = no contact, true = contact
// if the state has not changed, do nothing
if(contact == contact_state) return Event::ev_nothing;
contact_state = contact; // set the new state
// only care about when state changes to having contact
if(contact_state) {
// count HIGH->LOW transitions
contact_count = (contact_count + 1) % 3;
// 1 = first contact
// 2 = second contact (key on)
// 0 = release contact (key off)
switch(contact_count) {
case 2: // second contact
velocity = calc_velocity(millis() - first_contact);
return Event::ev_key_on;
case 0: return Event::ev_key_off; // release contact
case 1: first_contact = millis(); // first contact
}
}
return Event::ev_nothing;
}
};
Then define these globally:
constexpr std::uint8_t kNumberOfKeys = 49;
Key keys[kNumberOfKeys];
With that, your read_keys() function could look this this:
void read_keys() {
for (uint8_t key = 0; key < kNumberOfKeys; ++key) {
digitalWrite(output_main[key], LOW); //turn off output main key
// Do a digitalRead() and call the set() function for that key which will
// return an Event.
switch(keys[key].set( digitalRead(input_pullup[key]) == LOW )) {
case Event::ev_key_on:
my_midi.sendNoteOn(key + note_offset, keys[key].velocity, 1);
main_midi.sendNoteOn(key + note_offset, keys[key].velocity, 1);
break;
case Event::ev_key_off:
my_midi.sendNoteOff(key + note_offset, 0, 1);
main_midi.sendNoteOff(key + note_offset, 0, 1);
break;
case Event::ev_nothing:
default:
break;
}
digitalWrite(output_main[key], HIGH); //turn on output main key
}
}
This could be made so that each Key object would know which key number it actually is and so that it could read its own pin etc. It could also return an Event object which starts by turning off output main key and turns it back on when it's destroyed - but I think this leaves it more open since I don't know much about why the output main key should be turned off and on.
Disclaimer: I've ofcourse not been able to test this - so see it as building blocks.

How to allow my C++ code to update variables?

I'm new to coding and C++.
The code below is meant to monitor a magswitch and a status led on another controller. The code needs to run once the magswitch pin goes high (this works).
The additional code for pulseIn, is what I hope to use to monitor different flash rates of the led when I get the code working. For now I'm just looking for the state variable to update with the if and else if statements.
When I toggle the statusPin, the code picks up the changing state, but I cannot get it to update the "state" and "statuspinstate" variables.
The statuspinstate variable shows as 1, even though it is initialized as 0.
I inserted all the serial prints to try and see where things are going wrong.
This is the serial print when "statusPin" is LOW:
statuspinstate: 0
rate1: 2147483647
period: 0.00
rate2: 0
ontime: 0
offtime: 0
state: 0
statepinstatus: 1
This is the serial print when "statusPin" is HIGH
statuspinstate: 1
rate1: 2147483647
period: 0.00
rate2: 0
ontime: 0
offtime: 0
state: 0
statepinstatus: 1
Code:
const int statusPin = 19; //Reads status led
const int magSwitch = 22; //Magswitch to detect movement
int ontime,offtime,rate1,rate2;
float freq,period;
volatile unsigned int state =0;
volatile unsigned int statuspinstate = 0;
void setup()
{
pinMode(statusPin, INPUT); //input from controller
pinMode(magSwitch, INPUT);
Serial.begin(115200);
}
void loop()
{
while (digitalRead(magSwitch) == LOW) {
}
{
statuspinstate = digitalRead(statusPin);
ontime = pulseIn(statusPin,HIGH);
offtime = pulseIn(statusPin,LOW);
period = ontime+offtime;
rate1 = (ontime/period); //future use
rate2 = (offtime); //future use
Serial.println(String("statuspinstate ") + (digitalRead(statusPin))); //all serial print is debug info
Serial.println(String("rate1: ") + (rate1));
Serial.println(String("period: ") + (period));
Serial.println(String("rate2: ") + (rate2));
Serial.println(String("ontime: ") + (ontime));
Serial.println(String("offtime: ") + (offtime));
delay(500);
}
if ((ontime) != 0)
state = period;
else if (statuspinstate = 1)
state = 9999;
else if (statuspinstate = 0);
state = 0;
Serial.println(String("state: ") + (state));
Serial.println(String("statepinstatus: ") + (statuspinstate));
statuspinstate = 0; //return statuspinstate to zero
}
Look at your conditional, with proper indentation (do get a text editor that can indent your code for you):
if ((ontime) != 0)
state = period;
else if (statuspinstate = 1)
state = 9999;
else if (statuspinstate = 0);
state = 0;
We know that ontime is zero, so the second condition is tried next.
Now, statuspinstate = 1 is an assignment, not a comparison, and its value is "truth-y" so you take that branch.
Next, the stray semicolon in if (statuspinstate = 0); (which is also an assignment condition, but not evaluated) makes state = 0 unconditional.
So every time ontime is zero, you end up executing statuspinstate = 1 and state = 0.
What you probably want is
if (ontime != 0)
state = period;
else if (statuspinstate == 1)
state = 9999;
else if (statuspinstate == 0)
state = 0;

Waiting-time of thread switches systematicly between 0 and 30000 microseconds for the same task

I'm writing a little Console-Game-Engine and for better performance I wanted 2 threads (or more but 2 for this task) using two buffers. One thread is drawing the next frame in the first buffer while the other thread is reading the current frame from the second buffer. Then the buffers get swapped.
Of cause I can only swap them if both threads finished their task and the drawing/writing thread happened to be the one waiting. But the time it is waiting systematicly switches more or less between two values, here a few of the messurements I made (in microseconds):
0, 36968, 0, 36260, 0, 35762, 0, 38069, 0, 36584, 0, 36503
It's pretty obvious that this is not a coincidence but I wasn't able to figure out what the problem was as this is the first time I'm using threads.
Here the code, ask for more if you need it, I think it's too much to post it all:
header-file (Manager currently only adds a pointer to my WinAppBase-class):
class SwapChain : Manager
{
WORD *pScreenBuffer1, *pScreenBuffer2, *pWritePtr, *pReadPtr, *pTemp;
bool isRunning, writingFinished, readingFinished, initialized;
std::mutex lockWriting, lockReading;
std::condition_variable cvWriting, cvReading;
DWORD charsWritten;
COORD startPosition;
int screenBufferWidth;
// THREADS (USES NORMAL THREAD AS SECOND THREAD)
void ReadingThread();
// THIS FUNCTION IS ONLY FOR INTERN USE
void SwapBuffers();
public:
// USE THESE TO CONTROL WHEN THE BUFFERS GET SWAPPED
void BeginDraw();
void EndDraw();
// PUT PIXEL | INLINED FOR BETTER PERFORMANCE
inline void PutPixel(short xPos, short yPos, WORD color)
{
this->pWritePtr[(xPos * 2) + yPos * screenBufferWidth] = color;
this->pWritePtr[(xPos * 2) + yPos * screenBufferWidth + 1] = color;
}
// GENERAL CONTROL OVER SWAP CHAIN
void Initialize();
void Run();
void Stop();
// CONSTRUCTORS
SwapChain(WinAppBase * pAppBase);
virtual ~SwapChain();
};
Cpp-file
SwapChain::SwapChain(WinAppBase * pAppBase)
:
Manager(pAppBase)
{
this->isRunning = false;
this->initialized = false;
this->pReadPtr = NULL;
this->pScreenBuffer1 = NULL;
this->pScreenBuffer2 = NULL;
this->pWritePtr = NULL;
this->pTemp = NULL;
this->charsWritten = 0;
this->startPosition = { 0, 0 };
this->readingFinished = 0;
this->writingFinished = 0;
this->screenBufferWidth = this->pAppBase->screenBufferInfo.dwSize.X;
}
SwapChain::~SwapChain()
{
this->Stop();
if (_CrtIsValidHeapPointer(pReadPtr))
delete[] pReadPtr;
if (_CrtIsValidHeapPointer(pScreenBuffer1))
delete[] pScreenBuffer1;
if (_CrtIsValidHeapPointer(pScreenBuffer2))
delete[] pScreenBuffer2;
if (_CrtIsValidHeapPointer(pWritePtr))
delete[] pWritePtr;
}
void SwapChain::ReadingThread()
{
while (this->isRunning)
{
this->readingFinished = 0;
WriteConsoleOutputAttribute(
this->pAppBase->consoleCursor,
this->pReadPtr,
this->pAppBase->screenBufferSize,
this->startPosition,
&this->charsWritten
);
memset(this->pReadPtr, 0, this->pAppBase->screenBufferSize);
this->readingFinished = true;
this->cvWriting.notify_all();
if (!this->writingFinished)
{
std::unique_lock<std::mutex> lock(this->lockReading);
this->cvReading.wait(lock);
}
}
}
void SwapChain::SwapBuffers()
{
this->pTemp = this->pReadPtr;
this->pReadPtr = this->pWritePtr;
this->pWritePtr = this->pTemp;
this->pTemp = NULL;
}
void SwapChain::BeginDraw()
{
this->writingFinished = false;
}
void SwapChain::EndDraw()
{
TimePoint tpx1, tpx2;
tpx1 = Clock::now();
if (!this->readingFinished)
{
std::unique_lock<std::mutex> lock2(this->lockWriting);
this->cvWriting.wait(lock2);
}
tpx2 = Clock::now();
POST_DEBUG_MESSAGE(std::chrono::duration_cast<std::chrono::microseconds>(tpx2 - tpx1).count(), "EndDraw wating time");
SwapBuffers();
this->writingFinished = true;
this->cvReading.notify_all();
}
void SwapChain::Initialize()
{
if (this->initialized)
{
POST_DEBUG_MESSAGE(Result::CUSTOM, "multiple initialization");
return;
}
this->pScreenBuffer1 = (WORD *)malloc(sizeof(WORD) * this->pAppBase->screenBufferSize);
this->pScreenBuffer2 = (WORD *)malloc(sizeof(WORD) * this->pAppBase->screenBufferSize);
for (int i = 0; i < this->pAppBase->screenBufferSize; i++)
{
this->pScreenBuffer1[i] = 0x0000;
}
for (int i = 0; i < this->pAppBase->screenBufferSize; i++)
{
this->pScreenBuffer2[i] = 0x0000;
}
this->pWritePtr = pScreenBuffer1;
this->pReadPtr = pScreenBuffer2;
this->initialized = true;
}
void SwapChain::Run()
{
this->isRunning = true;
std::thread t1(&SwapChain::ReadingThread, this);
t1.detach();
}
void SwapChain::Stop()
{
this->isRunning = false;
}
This is where I run the SwapChain-class from:
void Application::Run()
{
this->engine.graphicsmanager.swapChain.Initialize();
Sprite<16, 16> sprite(&this->engine);
sprite.LoadSprite("engine/resources/TestData.xml", "root.test.sprites.baum");
this->engine.graphicsmanager.swapChain.Run();
int a, b, c;
for (int i = 0; i < 60; i++)
{
this->engine.graphicsmanager.swapChain.BeginDraw();
for (c = 0; c < 20; c++)
{
for (a = 0; a < 19; a++)
{
for (b = 0; b < 10; b++)
{
sprite.Print(a * 16, b * 16);
}
}
}
this->engine.graphicsmanager.swapChain.EndDraw();
}
this->engine.graphicsmanager.swapChain.Stop();
_getch();
}
The for-loops above simply draw the sprite 20 times from the top-left corner to the bottom-right corner of the console - the buffers don't get swapped during that, and that again for a total of 60 times (so the buffers get swapped 60 times).
sprite.Print uses the PutPixel function of SwapChain.
Here the WinAppBase (which consits more or less of global-like variables)
class WinAppBase
{
public:
// SCREENBUFFER
CONSOLE_SCREEN_BUFFER_INFO screenBufferInfo;
long screenBufferSize;
// CONSOLE
DWORD consoleMode;
HWND consoleWindow;
HANDLE consoleCursor;
HANDLE consoleInputHandle;
HANDLE consoleHandle;
CONSOLE_CURSOR_INFO consoleCursorInfo;
RECT consoleRect;
COORD consoleSize;
// FONT
CONSOLE_FONT_INFOEX fontInfo;
// MEMORY
char * pUserAccessDataPath;
public:
void reload();
WinAppBase();
virtual ~WinAppBase();
};
There are no errors, simply this alternating waitng time.
Maybe you'd like to start by looking if I did the synchronisation of the threads correctly? I'm not exactly sure how to use a mutex or condition-variables so it might comes from that.
Apart from that it is working fine, the sprites are shown as they should.
The clock you are using may have limited resolution. Here is a random example of a clock provided by Microsoft with 15 ms (15000 microsecond) resolution: Why are .NET timers limited to 15 ms resolution?
If one thread is often waiting for the other, it is entirely possible (assuming the above clock resolution) that it sometimes waits two clockticks and sometimes none. Maybe your clock only has 30 ms resolution. We really can't tell from the code. Do you get more precise measurements elsewhere with this clock?
There are also other systems in play such as the OS scheduler or whatever controls your std::threads. That one is (hopefully) much more granular, but how all these interactions play out doesn't have to be obvious or intuitive.

mBed C++ Using an RtosTimer inside of an RtosThread

I am writing some software to control a quadcopter and have got completely stuck with RtosTimers. I am getting the error "Error: No instance of constructor "rtos::RtosTimer::RtosTimer" matches the argument list in "flightController.h", Line: 13, Col: 29"
I have looked at the example code in the handbook and my code seems to match. I have also googled but I couldn't find anything on using RtosTimers inside of RtosThreads.
Maybe I am going about this the wrong way so if anyone has any suggestions it would be much appreciated.
Here is the code that is causing me problems
//Rtos Timers
RtosTimer UpdateFlightTimer(Task500Hz, osTimerPeriodic, (void *)0);
RtosTimer UpdateCommandTimer(Task50Hz, osTimerPeriodic, (void *)0);
// A thread to monitor the serial ports
void FlightControllerThread(void const *args)
{
UpdateFlightTimer.start(2);
UpdateCommandTimer.start(20);
// Wait here forever
Thread::wait(osWaitForever);
}
void Task500Hz(void const *n)
{
//Get IMU data and convert to yaw, pitch, roll
_freeIMU.getQ(_rawQuaternion);
_freeIMU.getRate(_gyroRate);
GetAttitude();
//Rate mode
if(_rate == true && _stab == false)
{
//Update rate PID process value with gyro rate
_yawRatePIDController->setProcessValue(_gyroRate[0]);
_pitchRatePIDController->setProcessValue(_gyroRate[2]);
_rollRatePIDController->setProcessValue(_gyroRate[1]);
//Update rate PID set point with desired rate from RC
_yawRatePIDController->setSetPoint(_rcConstrainedCommands[0]);
_pitchRatePIDController->setSetPoint(_rcConstrainedCommands[1]);
_rollRatePIDController->setSetPoint(_rcConstrainedCommands[2]);
//Compute rate PID outputs
_ratePIDControllerOutputs[0] = _yawRatePIDController->compute();
_ratePIDControllerOutputs[1] = _pitchRatePIDController->compute();
_ratePIDControllerOutputs[2] = _rollRatePIDController->compute();
}
//Stability mode
else
{
//Update stab PID process value with ypr
_yawStabPIDController->setProcessValue(_yrp[0]);
_pitchStabPIDController->setProcessValue(_yrp[2]);
_rollStabPIDController->setProcessValue(_yrp[1]);
//Update stab PID set point with desired angle from RC
_yawStabPIDController->setSetPoint(_yawTarget);
_pitchStabPIDController->setSetPoint(_rcConstrainedCommands[1]);
_rollStabPIDController->setSetPoint(_rcConstrainedCommands[2]);
//Compute stab PID outputs
_stabPIDControllerOutputs[0] = _yawStabPIDController->compute();
_stabPIDControllerOutputs[1] = _pitchStabPIDController->compute();
_stabPIDControllerOutputs[2] = _rollStabPIDController->compute();
//if pilot commanding yaw
if(abs(_rcConstrainedCommands[0]) > 5)
{
_stabPIDControllerOutputs[0] = _rcConstrainedCommands[0]; //Feed to rate PID (overwriting stab PID output)
_yawTarget = _yrp[0];
}
//Update rate PID process value with gyro rate
_yawRatePIDController->setProcessValue(_gyroRate[0]);
_pitchRatePIDController->setProcessValue(_gyroRate[2]);
_rollRatePIDController->setProcessValue(_gyroRate[1]);
//Update rate PID set point with desired rate from stab PID
_yawRatePIDController->setSetPoint(_stabPIDControllerOutputs[0]);
_pitchRatePIDController->setSetPoint(_stabPIDControllerOutputs[1]);
_rollRatePIDController->setSetPoint(_stabPIDControllerOutputs[2]);
//Compute rate PID outputs
_ratePIDControllerOutputs[0] = _yawRatePIDController->compute();
_ratePIDControllerOutputs[1] = _pitchRatePIDController->compute();
_ratePIDControllerOutputs[2] = _rollRatePIDController->compute();
}
//Calculate motor power if flying
if(_rcCommands[3] > 0 && _armed == true)
{
_motorPower[0] = Constrain(_rcConstrainedCommands[3] + _ratePIDControllerOutputs[1] + _ratePIDControllerOutputs[2] + _ratePIDControllerOutputs[0], MOTORS_MIN, MOTORS_MAX);
_motorPower[1] = Constrain(_rcConstrainedCommands[3] + _ratePIDControllerOutputs[1] - _ratePIDControllerOutputs[2] - _ratePIDControllerOutputs[0], MOTORS_MIN, MOTORS_MAX);
_motorPower[2] = Constrain(_rcConstrainedCommands[3] - _ratePIDControllerOutputs[1] - _ratePIDControllerOutputs[2] + _ratePIDControllerOutputs[0], MOTORS_MIN, MOTORS_MAX);
_motorPower[3] = Constrain(_rcConstrainedCommands[3] - _ratePIDControllerOutputs[1] + _ratePIDControllerOutputs[2] - _ratePIDControllerOutputs[0], MOTORS_MIN, MOTORS_MAX);
}
//Not flying
else
{
//Disable motors
_motorPower[0] = MOTORS_OFF;
_motorPower[1] = MOTORS_OFF;
_motorPower[2] = MOTORS_OFF;
_motorPower[3] = MOTORS_OFF;
_notFlying ++;
if(_notFlying > 200) //Not flying for 1 second
{
//Reset iteratior
_notFlying = 0;
//Zero gyro
_freeIMU.zeroGyro();
//Reset I
_yawRatePIDController->reset();
_pitchRatePIDController->reset();
_rollRatePIDController->reset();
_yawStabPIDController->reset();
_pitchStabPIDController->reset();
_rollStabPIDController->reset();
}
}
//Set motor power
_motor1.write(_motorPower[0]);
_motor2.write(_motorPower[1]);
_motor3.write(_motorPower[2]);
_motor4.write(_motorPower[3]);
}
void Task50Hz(void const *n)
{
//Get RC control values
//Constrain
//Rate mode
if(_rate == true && _stab == false)
{
_rcConstrainedCommands[0] = Constrain(_rcCommands[0], RC_YAW_RATE_MIN, RC_YAW_RATE_MAX);
_rcConstrainedCommands[1] = Constrain(_rcCommands[1], RC_PITCH_RATE_MIN, RC_PITCH_RATE_MAX);
_rcConstrainedCommands[2] = Constrain(_rcCommands[2], RC_ROLL_RATE_MIN, RC_ROLL_RATE_MAX);
_rcConstrainedCommands[3] = Constrain(_rcCommands[3], RC_THRUST_MIN, RC_THRUST_MAX);
}
else
{
_rcConstrainedCommands[0] = Constrain(_rcCommands[0], RC_YAW_RATE_MIN, RC_YAW_RATE_MAX);
_rcConstrainedCommands[1] = Constrain(_rcCommands[1], RC_PITCH_ANGLE_MIN, RC_PITCH_ANGLE_MAX);
_rcConstrainedCommands[2] = Constrain(_rcCommands[2], RC_ROLL_ANGLE_MIN, RC_ROLL_ANGLE_MAX);
_rcConstrainedCommands[3] = Constrain(_rcCommands[3], RC_THRUST_MIN, RC_THRUST_MAX);
}
}
My program can be found at http://mbed.org/users/joe4465/code/QuadMK5/
And the problem is in flightController.h I think it should be clear what I am trying to do but if anyone isn't sure let me know.
I also have another totally unrelated problem. I can set my PID variables over serial and then save them to a config file but 1 in 3 times if will hang just after it has saved the data to the file and I'm not sure why. Does anyone have any idea what could cause this?
Thanks Joe
I forgot to put void const *n in the parameters of the functions where they are defined at the top

Mutual exclusion and semaphores

I am writing a program (for homework) that simulates a unisex bathroom. Only 4 people are allowed at a time and men and woman cannot enter if the other sex is already using the bathroom. My problem is with allowing a max of 4 people in the bathroom. As you can see from the output, only 1 person is getting into the restroom at a time. Here is my code:
const int Delayx = 60;
int i;
int restroom = 0;
int Menwaiting = 0;
int Womenwaiting = 0;
semaphore max_capacity;
semaphore woman;
semaphore man;
semaphore mutex;
semaphore restroomcount;
void Delay(void)
{
int DelayTime;
DelayTime = random(Delayx);
for (i = 0; i<DelayTime; i++);
}
void Woman(void)
{
// for(;;){
Womenwaiting++;
//wait(mutex);
wait(woman);
wait(max_capacity);
//wait(woman);
wait(mutex);
wait(restroomcount);
cout << "A Woman has entered Restroom"<<endl;
cout << "People in the Restroom:" << restroom++ <<endl <<endl;
signal(restroomcount);
Womenwaiting--;
Delay();
wait(restroomcount);
cout << "A woman has exited Restroom"<<endl;
cout << "People in the Restroom:" << restroom-- <<endl<<endl;
signal(restroomcount);
signal(mutex);
signal(max_capacity);
if(Menwaiting > Womenwaiting){
signal(man);
}
else{
signal(woman);
}
//signal(max_capacity);
//signal(man);
// }
}
void Man(void)
{
// for(;;){
Menwaiting++;
//wait(mutex);
wait(man);
wait(max_capacity);
//wait(man);
wait(mutex);
wait(restroomcount);
cout <<"A Man has entered the Restroom"<<endl;
cout <<"People in the Restroom:" << restroom++ <<endl<<endl;
signal(restroomcount);
Menwaiting--;
//signal(mutex);
Delay();
//wait(mutex);
wait(restroomcount);
cout << "A man has exited the Restroom"<<endl;
cout <<"People in the Restroom:" << restroom-- <<endl<<endl;
signal(restroomcount);
signal(mutex);
signal(max_capacity);
if(Womenwaiting > Menwaiting){
signal(woman);
}
else{
signal(man);
}
//signal(max_capacity);
//signal(woman);
//}
}
void main()
{
initialsem(woman,1);
initialsem(man,1);
initialsem(max_capacity,4);
initialsem(mutex,1);
initialsem(restroomcount,1);
cobegin
{
Woman(); Woman(); Woman(); Woman(); Woman(); Man(); Man(); Man(); Man(); Man();
}
}
This generates the following output:
A Man has entered the Restroom
People in the Restroom:1
A man has exited the Restroom
People in the Restroom:0
A Man has entered the Restroom
People in the Restroom:1
A man has exited the Restroom
People in the Restroom:0
A Woman has entered Restroom
People in the Restroom:1
A woman has exited Restroom
People in the Restroom:0
A Woman has entered Restroom
People in the Restroom:1
A woman has exited Restroom
People in the Restroom:0
And so on, forever.
I think you have too many semaphores. Your man/woman semaphores are gating to 1 person at a time. Consider using some state variables protected by mutexes (current sex of bathroom, number of people in bathroom) rather than so many different semaphores.
Do you maintain a line ordering or can people skip based on the current restroom sex? For instance, if you have woman,woman,woman,man,woman, is the 4th woman allowed to skip the man and go into the restroom, or do the 3 women exit, then the man enters/exits, then the woman can enter? This is an easier problem than allowing a skip.
is the use of semaphores a requirement? for example, in "c++" pseudo-code, a implementation would look like:
First lets create a state object and a function that validates transitions between states
struct BathRoomState
{
int women;
int men;
BathRoomState( int w , int m ) : women(w) , men(m) {}
bool hasWomen()
{
if (women > 0 && men == 0)
return true;
return false;
}
bool isEmpty()
{
return (women + men == 0);
}
static bool isValidTransition( BathRoomState* a , BathRoomState* b )
{
if (a->HasWomen())
{
if ( (abs( a->women - b->women ) == 1) && (a->men == b->men) )
return true;
else false;
} else if (a->isEmpty())
{
if ((b->women == 1 && b->men == 0)
|| (b->women == 0 && b->men == 1))
return true else false;
} else //a has men
{
if ((abs( a->men - b->men ) == 1) && ( a->women == b->women))
return true else false;
}
}
}
Lets also create a global reference to the current state and a function to update the current state based on some next desired state
BathRoomState* currentBathroomState = 0;
bool TryToChangeState(BathRoomState* newState)
{
BathRoomState* existingState = currentBathroomState;
if (BathRoomState::isValidTransition( existingState , newState ))
{
//this atomic operation depends on library support
bool success = CompareAndSwapAtomically( currentBathroomState , existingState , newState );
return success;
}
}
then we create a global vector to hold the states, and a function representing a women thread trying to go to the bathroom
std::vector< BathRoomState* > noGCinThisExample;
//thread functtion
void women()
{
BathRoomState* existingState = currentBathroomState;
BathRoomState* newState = new BathRoomState( existingState.women+1 , existingState.men );
while (!TryToChangeState(newState))
{
//yield or sleep from time to time here to let other threads progress
existingState = currentBathroomState;
newState.women = existingState.women + 1;
newState.men = existingState.men;
}
noGCinThisExample.push_back( newState ); //no GC in this example
//the woman is in the bathroom now. lets give her some time
delayForWomen();
//lets try to get her out
BathRoomState* exitState = new BathRoomState( existingState.women-1 , existingState.men );
while (!TryToChangeState(exitState ))
{
//yield or sleep from time to time here to let other threads progress
existingState = currentBathroomState;
exitState.women = existingState.women - 1;
exitState.men = existingState.men;
}
noGCinThisExample.push_back( exitState); //no GC in this example
}
//homework: do a similar function for men
and the main function with process loop logic and initialization
void main()
{
BathRoomState* initialState = new BathRoomState( 0 , 0);
noGCinThisExample.push_back( initialState );
currentBathroomState = initialState;
while(some_condition)
{
if (random() > 0.5)
thread( women() );
else
thread( men() );
}
};
this code should work ( i haven't tested it ). I've cheated a bit because i'm not deleting any of the provisional states created, so each state persist until the process dies. proper garbage collection would require a technique called hazard pointer management.
Note that i dont use any mutex semaphores or lock, the only locking primitive i am using is the CAS( address, old_value , new_value ) (compare and swap). This primitive atomically compares a pointer (address) and if it still contains (old_value) then it assign it new_value and succeeds, otherwise it fails. Also, you still need a global lock for the std::vector storing the states that i have not included in the code (you can also just leak them, but i store them somewhere so you can think that those should be deleted once you know how GC could be made to work in these cases)
Since all my intermediate states are inmutable (lisp/clojure style inmutabilitity) the contention (and hence, starvation) of the threads vastly improves. In your example the set of states is small (just a bunch of persons) its not too bad that we don't delete the used states.
however, even with the problems i've mentioned, i think you would agree that the logic of what is happening is much more explicit and readable.
Issues with the question
The original code isn't very OO.
The processing of the bathroom queue should be seperate from the generation of the people in the queue - if not running a seperate thread at least after the queue is filled.
Making the assumption that there are basically separate queues of men and women - not intermixed in some fixed order, otherwise the problem doesn't make any sense to use a semaphore.
The problem doesn't describe how many people get to enter when the condition is right, male toilet with more men, do you fill it to 4 or only until the queue of men is less than women again?
Even so the problem as described (and based on sample code with no threading) doesn't work well with a semaphore in my opinion, the main problem is that the semaphore doesn't yield the count easily and a successful wait changes the count.
The interesting thing I see in the problem is the inefficiency in a near equal queue length and trading between disallowing another of the same sex into the toilet and the chance that before the remaining persons in the toilet leave the number of the same sex becomes larger again. Lets face it, it's unisex and so it should allow 4 people in regardless of gender ;)
Proposed solution
So you need to use a semaphore, the interesting things about a semaphore is the recording of multiple uses (unlike mutex) and if there is not free space then it will possibly wait. It does not discriminate however between those waiting, it will only tell that there is space free.
Have 1 semaphore and think you should check the semaphore when a person enters the queue or when somebody leaves the bathroom.
You could then have 1 'queue' each for men and women (from given this is basically a count). These queues are not really related or limiting on each other in terms of entry and so have nothing to do with semaphores. Each could follow a locking free provider pattern, but you might find it easier to use a mutex to synchronise so that you can examine the size of the queues and manipulate them. In the following I've just used the count directly, instead it should be using some form of InterlockedIncrement and InterlockedDecrement to protect against adding and removing people from the same queue.
In the rough, Bathroom.h
class Bathroom
{
public:
Bathroom(void);
~Bathroom(void);
AddMan();
AddWoman();
Run();
private:
StateChange();
int m_Menwaiting;
int m_Womenwaiting;
semaphore max_capacity;
enum Users {
NOBODY ,
WOMEN,
MEN
} m_inUseBy;
};
Bathroom.cpp
Bathroom::Bathroom(void)
: m_Menwaiting(0)
, m_Womenwaiting(0)
, m_inUseBy(NOBODY)
{
initialsem(max_capacity,4);
}
Bathroom::~Bathroom(void)
{
freesem(max_capacity);
}
Bathroom::AddMan(){
++m_Menwaiting;
StateChange();
}
Bathroom::AddWoman(){
++m_Womenwaiting;
StateChange();
}
Bathroom::StateChange() {
// extra at a time
if( m_Menwaiting > m_Womenwaiting && inUseBy != WOMEN ) {
if( wait(max_capacity,0 delay) != timeout )
m_Menwaiting--;
}
if( m_Womenwaiting > m_Menwaiting && inUseBy != MEN ) {
if( wait(max_capacity,0 delay) != timeout )
m_Womenwaiting--;
}
// all available slots
if( m_Menwaiting > m_Womenwaiting && inUseBy != WOMEN ) {
while( wait(max_capacity,0 delay) != timeout )
m_Menwaiting--;
}
if( m_Womenwaiting > m_Menwaiting && inUseBy != MEN ) {
while( wait(max_capacity,0 delay) != timeout )
m_Womenwaiting--;
}
}
Bathroom::run(){
// people leaving bathroom simulated
while(1) {
Delay();
signal(max_capacity);
StateChange();
}
}
Program.cpp
Bathroom b1;
addPeople() {
while(true) {
// randomly add people
Delay();
b1.AddMen();
b1.AddWomen();
}
}
int main(){
thread( addPeople );
b1.run();
}