Get class object pointer from inside a static method called directly - c++

I have the following class, for example in a header:
class Uart
{
public:
Uart (int ch, int bd = 9600, bool doinit = false);
......
static void isr (void);
}
The idea is this class represents USART hardware, the same way as SPI, RTC etc and I set the address of static member isr as interrupt vector routine during runtime.
For example like this
extern "C"
{
void
Uart::isr (void)
{
if ( USART1->SR & USART_SR_RXNE) //receive
{
short c = USART2->DR;
USART1->DR = c;
USART1->SR &= ~USART_SR_RXNE;
;
}
else if ( USART1->SR & USART_SR_TC) //transfer
{
USART1->SR &= ~USART_SR_TC;
}
}
}
And set it as a interrupt vector, for example
_vectors_[USART1_IRQn + IRQ0_EX] = (word) &dbgout.isr;
So each time this "callback" routine is called by CPU I want to get access to it's "parent" object to save and/or manipulate the received data in userfriendly manner.
Is it possible at all? Maybe somehow organize the class or whatever.
The architecture is strictly 32bit (ARM, gcc)

Static methods know nothing about the object.
You need a different approach:
// Create interrupt handler method (non-static!)
void Uart::inthandler() {
// whatever is needed here
}
// Create object
Uart* p = new Uart(...);
// Create interrupt handler function
void inthandler() {
if (p != NULL) {
p->inthandler();
}
}
// Install the interrupt handler function
InstallIntHandler(IRQ, inthandler);
It's just a principle that has to be adapted to your specific environment.

Related

Avoiding data race condition between two ROS subscriber callback funtions

Let's suppose we've two ROS subscriber callback functions where the callback is called every time a new message is extracted from the queue and we want to use the value of a callback in another callback and vice versa.
I've implemented this in a class with two member variables that store my data.
I suspect a possible race condition between the two callbacks. I tried to create a simple example below.
class <class_name>
{
public:
<var_1_type> get_var_1() {
return var_1;
}
set_var_1(const <var_1_type> value) {
var_1 = value;
}
<var_2_type> get_var_2() {
return var_2;
}
set_var_2(const <var_2_type> value) {
var_2 = value;
}
private:
<var_1_type> var_1;
<var_2_type> var_2;
void callback_function_1(<msg_type> &msg_holder);
void callback_function_2(<msg_type> &msg_holder);
};
void <class_name>::callback_function_1(<msg_type> &msg_holder)
{
set_var_1(msg_holder.data);
// Use var_1 and var_2 to create a new data, e.g.,
<var_3_type> var_3 = get_var_1() * get_var_2();
// Now we can publish the var_3, which is the output of the node.
var_3_pub.publish(var_3);
}
void <class_name>::callback_function_2(<msg_type> &msg_holder)
{
// Use the var_1 and msg_holder.data to calculate var_2, e.g.,
<var_2_type> var_2_ = get_var_1() + msg_holder.data;
set_var_2(var_2_);
}
int main(int argc, char** argv)
{
// Instantiate an object of type <class_name>
// Go into ros spin and let the callback functions do all the work.
return 0;
}
In my particular application, var_1 and var_2 are in fact, 2D vectors that can be thought as a matrix, I don't want the contents of the matrix to be modified by one callback function while it's being used by the other callback function.
I'm somewhat familiar with the use of std::lock_guard<std::mutex> guard(mu);, mu.lock();, mu.unlock(). However, I cannot immediately see a way of using <mutex> in this case. Any help is appreciated.
You simply can make use of a Lock Guard using the same mutex instance in each of your callbacks like:
std::mutex mutex_;
void <class_name>::callback_function_1(<msg_type> &msg_holder)
{
const std::lock_guard<std::mutex> lock(mutex_);
//Locked code here
//The mutex is automatically released when lock goes out of scope (function left)
}
void <class_name>::callback_function_2(<msg_type> &msg_holder)
{
const std::lock_guard<std::mutex> lock(mutex_);
//Locked code here
//The mutex is automatically released when lock goes out of scope (function left)
}
The complete code in your callbacks is executed threadsafe with this solution. Note that you also are able to lock more specific parts of your function by creating a thighter scope { ... }.

Readable node stream to native c++ addon InputStream

Conceptually what I'm trying to do is very simple. I have a Readable stream in node, and I'm passing that to a native c++ addon where I want to connect that to an IInputStream.
The native library that I'm using works like many c++ (or Java) streaming interfaces that I've seen. The library provides an IInputStream interface (technically an abstract class), which I inherit from and override the virtual functions. Looks like this:
class JsReadable2InputStream : public IInputStream {
public:
// Constructor takes a js v8 object, makes a stream out of it
JsReadable2InputStream(const v8::Local<v8::Object>& streamObj);
~JsReadable2InputStream();
/**
* Blocking read. Blocks until the requested amount of data has been read. However,
* if the stream reaches its end before the requested amount of bytes has been read
* it returns the number of bytes read thus far.
*
* #param begin memory into which read data is copied
* #param byteCount the requested number of bytes
* #return the number of bytes actually read. Is less than bytesCount iff
* end of stream has been reached.
*/
virtual int read(char* begin, const int byteCount) override;
virtual int available() const override;
virtual bool isActive() const override;
virtual void close() override;
private:
Nan::Persistent<v8::Object> _stream;
bool _active;
JsEventLoopSync _evtLoop;
};
Of these functions, the important one here is read. The native library will call this function when it wants more data, and the function must block until it is able to return the requested data (or the stream ends). Here's my implementation of read:
int JsReadable2InputStream::read(char* begin, const int byteCount) {
if (!this->_active) { return 0; }
int read = -1;
while (read < 0 && this->_active) {
this->_evtLoop.invoke(
(voidLambda)[this,&read,begin,byteCount](){
v8::Local<v8::Object> stream = Nan::New(this->_stream);
const v8::Local<v8::Function> readFn = Nan::To<v8::Function>(Nan::Get(stream, JS_STR("read")).ToLocalChecked()).ToLocalChecked();
v8::Local<v8::Value> argv[] = { Nan::New<v8::Number>(byteCount) };
v8::Local<v8::Value> result = Nan::Call(readFn, stream, 1, argv).ToLocalChecked();
if (result->IsNull()) {
// Somewhat hacky/brittle way to check if stream has ended, but it's the only option
v8::Local<v8::Object> readableState = Nan::To<v8::Object>(Nan::Get(stream, JS_STR("_readableState")).ToLocalChecked()).ToLocalChecked();
if (Nan::To<bool>(Nan::Get(readableState, JS_STR("ended")).ToLocalChecked()).ToChecked()) {
// End of stream, all data has been read
this->_active = false;
read = 0;
return;
}
// Not enough data available, but stream is still open.
// Set a flag for the c++ thread to go to sleep
// This is the case that it gets stuck in
read = -1;
return;
}
v8::Local<v8::Object> bufferObj = Nan::To<v8::Object>(result).ToLocalChecked();
int len = Nan::To<int32_t>(Nan::Get(bufferObj, JS_STR("length")).ToLocalChecked()).ToChecked();
char* buffer = node::Buffer::Data(bufferObj);
if (len < byteCount) {
this->_active = false;
}
// copy the data out of the buffer
if (len > 0) {
std::memcpy(begin, buffer, len);
}
read = len;
}
);
if (read < 0) {
// Give js a chance to read more data
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
return read;
}
The idea is, the c++ code keeps a reference to the node stream object. When the native code wants to read, it has to synchronize with the node event loop, then attempt to invoke read on the node stream. If the node stream returns null, this indicates that the data isn't ready, so the native thread sleeps, giving the node event loop thread a chance to run and fill its buffers.
This solution works perfectly for a single stream, or even 2 or 3 streams running in parallel. Then for some reason when I hit the magical number of 4+ parallel streams, this totally deadlocks. None of the streams can successfully read any bytes at all. The above while loop runs infinitely, with the call into the node stream returning null every time.
It is behaving as though node is getting starved, and the streams never get a chance to populate with data. However, I've tried adjusting the sleep duration (to much larger values, and randomized values) and that had no effect. It is also clear that the event loop continues to run, since my lambda function continues to get executed there (I put some printfs inside to confirm this).
Just in case it might be relevant (I don't think it is), I'm also including my implementation of JsEventLoopSync. This uses libuv to schedule a lambda to be executed on the node event loop. It is designed such that only one can be scheduled at a time, and other invocations must wait until the first completes.
#include <nan.h>
#include <functional>
// simplified type declarations for the lambda functions
using voidLambda = std::function<void ()>;
// Synchronize with the node v8 event loop. Invokes a lambda function on the event loop, where access to js objects is safe.
// Blocks execution of the invoking thread until execution of the lambda completes.
class JsEventLoopSync {
public:
JsEventLoopSync() : _destroyed(false) {
// register on the default (same as node) event loop, so that we can execute callbacks in that context
// This takes a function pointer, which only works with a static function
this->_handles = new async_handles_t();
this->_handles->inst = this;
uv_async_init(uv_default_loop(), &this->_handles->async, JsEventLoopSync::_processUvCb);
// mechanism for passing this instance through to the native uv callback
this->_handles->async.data = this->_handles;
// mutex has to be initialized
uv_mutex_init(&this->_handles->mutex);
uv_cond_init(&this->_handles->cond);
}
~JsEventLoopSync() {
uv_mutex_lock(&this->_handles->mutex);
// prevent access to deleted instance by callback
this->_destroyed = true;
uv_mutex_unlock(&this->_handles->mutex);
// NOTE: Important, this->_handles must be a dynamically allocated pointer because uv_close() is
// async, and still has a reference to it. If it were statically allocated as a class member, this
// destructor would free the memory before uv_close was done with it (leading to asserts in libuv)
uv_close(reinterpret_cast<uv_handle_t*>(&this->_handles->async), JsEventLoopSync::_asyncClose);
}
// called from the native code to invoke the function
void invoke(const voidLambda& fn) {
if (v8::Isolate::GetCurrent() != NULL) {
// Already on the event loop, process now
return fn();
}
// Need to sync with the event loop
uv_mutex_lock(&this->_handles->mutex);
if (this->_destroyed) { return; }
this->_fn = fn;
// this will invoke processUvCb, on the node event loop
uv_async_send(&this->_handles->async);
// wait for it to complete processing
uv_cond_wait(&this->_handles->cond, &this->_handles->mutex);
uv_mutex_unlock(&this->_handles->mutex);
}
private:
// pulls data out of uv's void* to call the instance method
static void _processUvCb(uv_async_t* handle) {
if (handle->data == NULL) { return; }
auto handles = static_cast<async_handles_t*>(handle->data);
handles->inst->_process();
}
inline static void _asyncClose(uv_handle_t* handle) {
auto handles = static_cast<async_handles_t*>(handle->data);
handle->data = NULL;
uv_mutex_destroy(&handles->mutex);
uv_cond_destroy(&handles->cond);
delete handles;
}
// Creates the js arguments (populated by invoking the lambda), then invokes the js function
// Invokes resultLambda on the result
// Must be run on the node event loop!
void _process() {
if (v8::Isolate::GetCurrent() == NULL) {
// This is unexpected!
throw std::logic_error("Unable to sync with node event loop for callback!");
}
uv_mutex_lock(&this->_handles->mutex);
if (this->_destroyed) { return; }
Nan::HandleScope scope; // looks unused, but this is very important
// invoke the lambda
this->_fn();
// signal that we're done
uv_cond_signal(&this->_handles->cond);
uv_mutex_unlock(&this->_handles->mutex);
}
typedef struct async_handles {
uv_mutex_t mutex;
uv_cond_t cond;
uv_async_t async;
JsEventLoopSync* inst;
} async_handles_t;
async_handles_t* _handles;
voidLambda _fn;
bool _destroyed;
};
So, what am I missing? Is there a better way to wait for the node thread to get a chance to run? Is there a totally different design pattern that would work better? Does node have some upper limit on the number of streams that it can process at once?
As it turns out, the problems that I was seeing were actually client-side limitations. Browsers (and seemingly also node) have a limit on the number of open TCP connections to the same origin. I worked around this by spawning multiple node processes to do my testing.
If anyone is trying to do something similar, the code I shared is totally viable. If I ever have some free time, I might make it into a library.

Allow native C++ components to raise CLR Asynchronous events

I need in my Native code to raise an asynchronous event to C#,I have used as bridge CLI ,actually I have gone though sending a pointer to function from C++/CLI but it did not work properly?
I need to know:1-What is wrong? 2-how can make it asynchronous event to not block the processing?
I need in this example to raise an event each time I reach 1000,here is my code
Count.h
typedef void pointertofunc(bool IsOverFlowOccured);
typedef pointertofunc *pointertofuncdelegate;
class count
{
public:
void startCounting(pointertofuncdelegate);
count();
~count();
};
Count.cpp
void count::startCounting(pointertofuncdelegate)
{
for (int i = 0; i < 100000; i++)
{
//printf("%d \n", i);
if (i == 1000)
{
pointertofuncdelegate(true);
printf("%d \n", i);
i = 0;
}
}
}
CLR(.h file)
public delegate void manageddelegate(bool isworkflowoccured);
ref class CounterRaiseAsynchronousEvent
{
public:
event manageddelegate^ managedEventHandler;
CounterRaiseAsynchronousEvent();
void initialize();
void raiseEvent(bool eoverFlow);
private:
count* wrapperObject;
};
CLR(.cpp file)
void CounterRaiseAsynchronousEvent::initialize()
{
//Create a new delegate and point it to the member function
manageddelegate^ prDel = gcnew manageddelegate(this, &CounterRaiseAsynchronousEvent::raiseEvent);
GCHandle gch = GCHandle::Alloc(prDel);
//Convert the delegate to a function pointer
IntPtr ip = Marshal::GetFunctionPointerForDelegate(prDel);
//... and cast it to the appropriate type
pointertofuncdelegate fp = static_cast<pointertofuncdelegate>(ip.ToPointer());
//set the native function pointer on the native class
wrapperObject->startCounting(fp);
}
void CounterRaiseAsynchronousEvent::raiseEvent(bool isOverflowOccurred)
{
//Do any thing
}
It's not usually a good idea for the event source to implement an asynchronous handling model -- that forces the client code to be multi-threaded and do synchronization, and causes complications when different components have chosen different models.
Instead, call events synchronously, and let the subscriber pend the callback and return immediately. This is compatible with any asynchronous model the client code prefers, such as native PostMessage or Control.BeginInvoke or TPL (async/await) or worker threadpool.

Pointers to member functions within the same class (C++)?

I am writing a program to control a auto home brewing system on an Arduino Mega micro controller (written in C/C++). In short, what the program is doing is there is a C# application which periodically sends messages through USB to the micro controller. There is then a messaging interface which I wrote which reads the message, and forwards it to whichever component the message is for. Each message is 16 bytes long, the first 4 is a transaction code, and the last 12 is for data. Now, I read in the message and forward to it to my StateController class. It comes in from the InboundMessage function. What I am trying to do is I have a struct (defined in StateController.h) which contains the transaction code and pointer to a member function within StateController. I defined a QueueList (just a simple linked list library), and pushed a bunch of these structs into it. What I would like to do is then when a message comes into the inboundMessage function, i would like to loop through the linked list until I find a transaction code which matches, and then call the member function which is for that message, passing it the data in the message.
I think I have everything initialized correctly, but here is the problem. When I try and compile I get an error saying "func does not exist in this scope". I have looked all over for a solution to this, but can not find one. My codes is below
StateController.cpp
StateController::StateController(){
currentState = Idle;
prevState = Idle;
lastRunState = Idle;
txnTable.push((txnRow){MSG_BURN, &StateController::BURNprocessor});
txnTable.push((txnRow){MSG_MANE, &StateController::MANEprocessor});
txnTable.push((txnRow){MSG_MAND, &StateController::MANDprocessor});
txnTable.push((txnRow){MSG_PUMP, &StateController::PUMPprocessor});
txnTable.push((txnRow){MSG_STAT, &StateController::STATprocessor});
txnTable.push((txnRow){MSG_SYNC, &StateController::SYNCprocessor});
txnTable.push((txnRow){MSG_VALV, &StateController::VALVprocessor});
}
void StateController::inboundMessage(GenericMessage msg){
// Read transaction code and do what needs to be done for it
for (int x = 0; x < txnTable.count(); x++)
{
if (compareCharArr(msg.code, txnTable[x].code, TXN_CODE_LEN) == true)
{
(txnTable[x].*func)(msg.data);
break;
}
}
}
StateController.h
class StateController{
// Public functions
public:
// Constructor
StateController();
// State Controller message handeler
void inboundMessage(GenericMessage msg);
// Main state machine
void doWork();
// Private Members
private:
// Hardware interface
HardwareInterface hardwareIntf;
// Current state holder
StateControllerStates currentState;
// Preveous State
StateControllerStates prevState;
// Last run state
StateControllerStates lastRunState;
// BURN Message Processor
void BURNprocessor(char data[]);
// MANE Message Processor
void MANEprocessor(char data[]);
// MAND Message Processor
void MANDprocessor(char data[]);
// PUMP Message Processor
void PUMPprocessor(char data[]);
//STAT Message Processor
void STATprocessor(char data[]);
// SYNC Message Processor
void SYNCprocessor(char data[]);
// VALV Message Processor
void VALVprocessor(char data[]);
void primePumps();
// Check the value of two sensors given the window
int checkSensorWindow(int newSensor, int prevSensor, int window);
struct txnRow{
char code[TXN_CODE_LEN + 1];
void (StateController::*func)(char[]);
};
QueueList<txnRow> txnTable;
};
Any idea what is wrong?
func is just a normal member of txnRow so you access it with ., not .*, e.g. txnTable[x].func.
To call this member function on, say, this, you would do something like:
(this->*(txnTable[x].func))(msg.data);

C++ Critical Section not working

My critical section code does not work!!!
Backgrounder.run IS able to modify MESSAGE_QUEUE g_msgQueue and LockSections destructor hadn't been called yet !!!
Extra code :
typedef std::vector<int> MESSAGE_LIST; // SHARED OBJECT .. MUST LOCK!
class MESSAGE_QUEUE : MESSAGE_LIST{
public:
MESSAGE_LIST * m_pList;
MESSAGE_QUEUE(MESSAGE_LIST* pList){ m_pList = pList; }
~MESSAGE_QUEUE(){ }
/* This class will be shared between threads that means any
* attempt to access it MUST be inside a critical section.
*/
void Add( int messageCode ){ if(m_pList) m_pList->push_back(messageCode); }
int getLast()
{
if(m_pList){
if(m_pList->size() == 1){
Add(0x0);
}
m_pList->pop_back();
return m_pList->back();
}
}
void removeLast()
{
if(m_pList){
m_pList->erase(m_pList->end()-1,m_pList->end());
}
}
};
class Backgrounder{
public:
MESSAGE_QUEUE* m_pMsgQueue;
static void __cdecl Run( void* args){
MESSAGE_QUEUE* s_pMsgQueue = (MESSAGE_QUEUE*)args;
if(s_pMsgQueue->getLast() == 0x45)printf("It's a success!");
else printf("It's a trap!");
}
Backgrounder(MESSAGE_QUEUE* pMsgQueue)
{
m_pMsgQueue = pMsgQueue;
_beginthread(Run,0,(void*)m_pMsgQueue);
}
~Backgrounder(){ }
};
int main(){
MESSAGE_LIST g_List;
CriticalSection crt;
ErrorHandler err;
LockSection lc(&crt,&err); // Does not work , see question #2
MESSAGE_QUEUE g_msgQueue(&g_List);
g_msgQueue.Add(0x45);
printf("%d",g_msgQueue.getLast());
Backgrounder back_thread(&g_msgQueue);
while(!kbhit());
return 0;
}
#ifndef CRITICALSECTION_H
#define CRITICALSECTION_H
#include <windows.h>
#include "ErrorHandler.h"
class CriticalSection{
long m_nLockCount;
long m_nThreadId;
typedef CRITICAL_SECTION cs;
cs m_tCS;
public:
CriticalSection(){
::InitializeCriticalSection(&m_tCS);
m_nLockCount = 0;
m_nThreadId = 0;
}
~CriticalSection(){ ::DeleteCriticalSection(&m_tCS); }
void Enter(){ ::EnterCriticalSection(&m_tCS); }
void Leave(){ ::LeaveCriticalSection(&m_tCS); }
void Try();
};
class LockSection{
CriticalSection* m_pCS;
ErrorHandler * m_pErrorHandler;
bool m_bIsClosed;
public:
LockSection(CriticalSection* pCS,ErrorHandler* pErrorHandler){
m_bIsClosed = false;
m_pCS = pCS;
m_pErrorHandler = pErrorHandler;
// 0x1AE is code prefix for critical section header
if(!m_pCS)m_pErrorHandler->Add(0x1AE1);
if(m_pCS)m_pCS->Enter();
}
~LockSection(){
if(!m_pCS)m_pErrorHandler->Add(0x1AE2);
if(m_pCS && m_bIsClosed == false)m_pCS->Leave();
}
void ForceCSectionClose(){
if(!m_pCS)m_pErrorHandler->Add(0x1AE3);
if(m_pCS){m_pCS->Leave();m_bIsClosed = true;}
}
};
/*
Safe class basic structure;
class SafeObj
{
CriticalSection m_cs;
public:
void SafeMethod()
{
LockSection myLock(&m_cs);
//add code to implement the method ...
}
};
*/
#endif
Two questions in one. I don't know about the first, but the critical section part is easy to explain. The background thread isn't trying to claim the lock and so, of course, is not blocked. You need to make the critical section object crt visible to the thread so that it can lock it.
The way to use this lock class is that each section of code that you want serialised must create a LockSection object and hold on to it until the end of the serialised block:
Thread 1:
{
LockSection lc(&crt,&err);
//operate on shared object from thread 1
}
Thread 2:
{
LockSection lc(&crt,&err);
//operate on shared object from thread 2
}
Note that it has to be the same critical section instance crt that is used in each block of code that is to be serialised.
This code has a number of problems.
First of all, deriving from the standard containers is almost always a poor idea. In this case you're using private inheritance, which reduces the problems, but doesn't eliminate them entirely. In any case, you don't seem to put the inheritance to much (any?) use anyway. Even though you've derived your MESSAGE_QUEUE from MESSAGE_LIST (which is actually std::vector<int>), you embed a pointer to an instance of a MESSAGE_LIST into MESSAGE_QUEUE anyway.
Second, if you're going to use a queue to communicate between threads (which I think is generally a good idea) you should make the locking inherent in the queue operations rather than requiring each thread to manage the locking correctly on its own.
Third, a vector isn't a particularly suitable data structure for representing a queue anyway, unless you're going to make it fixed size, and use it roughly like a ring buffer. That's not a bad idea either, but it's quite a bit different from what you've done. If you're going to make the size dynamic, you'd probably be better off starting with a deque instead.
Fourth, the magic numbers in your error handling (0x1AE1, 0x1AE2, etc.) is quite opaque. At the very least, you need to give these meaningful names. The one comment you have does not make the use anywhere close to clear.
Finally, if you're going to go to all the trouble of writing code for a thread-safe queue, you might as well make it generic so it can hold essentially any kind of data you want, instead of dedicating it to one specific type.
Ultimately, your code doesn't seem to save the client much work or trouble over using the Windows functions directly. For the most part, you've just provided the same capabilities under slightly different names.
IMO, a thread-safe queue should handle almost all the work internally, so that client code can use it about like it would any other queue.
// Warning: untested code.
// Assumes: `T::T(T const &) throw()`
//
template <class T>
class queue {
std::deque<T> data;
CRITICAL_SECTION cs;
HANDLE semaphore;
public:
queue() {
InitializeCriticalSection(&cs);
semaphore = CreateSemaphore(NULL, 0, 2048, NULL);
}
~queue() {
DeleteCriticalSection(&cs);
CloseHandle(semaphore);
}
void push(T const &item) {
EnterCriticalSection(&cs);
data.push_back(item);
LeaveCriticalSection(&cs);
ReleaseSemaphore(semaphore, 1, NULL);
}
T pop() {
WaitForSingleObject(semaphore, INFINITE);
EnterCriticalSection(&cs);
T item = data.front();
data.pop_front();
LeaveCriticalSection(&cs);
return item;
}
};
HANDLE done;
typedef queue<int> msgQ;
enum commands { quit, print };
void backgrounder(void *qq) {
// I haven't quite puzzled out what your background thread
// was supposed to do, so I've kept it really simple, executing only
// the two commands listed above.
msgQ *q = (msgQ *)qq;
int command;
while (quit != (command = q->pop()))
printf("Print\n");
SetEvent(done);
}
int main() {
msgQ q;
done = CreateEvent(NULL, false, false, NULL);
_beginthread(backgrounder, 0, (void*)&q);
for (int i=0; i<20; i++)
q.push(print);
q.push(quit);
WaitForSingleObject(done, INFINITE);
return 0;
}
Your background thread needs access to the same CriticalSection object and it needs to create LockSection objects to lock it -- the locking is collaborative.
You are trying to return the last element after popping it.