Can I make sure a specific child thread acquires a lock if I have its id? (Using pthreads library in C++) - pthreads

I want to release the lock I've acquired within the main process and hand it over to a specific thread. Is there a way I can do this? I'm using the pthreads library

I want to release the lock I've acquired within the main process and hand it over to a specific thread.
This implies that multiple threads want to acquire this lock.
If it matters which one of these threads actually gets it, your design is very likely wrong.
Is there a way I can do this?
No.

Related

Why does MacOS/iOS *force* the main thread to be the UI thread, and are there any workarounds?

First off, I'd like to clarify that I'm not talking about concurrency here. I fully understand that having multiple threads modify the UI at the same time is bad, can give race conditions, deadlocks, bugs etc, but that's separate to my question.
I'd like to know why MacOS/iOS forces the main thread (ID 0, first thread, whatever) to be the thread on which the GUI must be used/updated/created on.
see here, related:
on OSX/iOS the GUI must always be updated from the main thread, end of story.
I understand that you only ever want a single thread doing the acutal updating of the GUI, but why does that thread have to be ID 0?
(this is background info, TLDR below)
In my case, I'm making a rust app that uses a couple of threads to do things:
engine - does processing and calculations
ui - self explanatory
program/main - monitors other threads and generally synchronizes things
I'm currently doing something semi-unsafe and creating the UI on it's own thread, which works since I'm on windows, but the API is explicitly marked as BAD to use, and it's not cross compatible for MacOS/iOS for obvious reasons (and I want it to be as compatible as possible).
With the UI/engine threads (there may be more in the future), they are semi-unstable and could crash/exit early, outside of my control (external code). This has happened before, and so I want to have a graceful shutdown if anything goes wrong, hence the 'main' thread monitoring (among other things it does).
I am aware that I could just make Thread 0 the UI thread and move the program to another thread, but the app will immediately quit when the main thread quits, which means if the UI crashes the whole things just aborts (and I don't want this). Essentially, I need my main function on the main thread, since I know it won't suddenly exit and abort the whole app abruptly.
TL;DR
Overall, I'd like to know three things
Why does MacOS/iOS enforce the GUI being on THread 0 (ignoring thread-safety outlined above)
Are there any ways to bypass this (use a different thread for GUI), or will I simply need to sacrifice those platforms (and possible others I'm unaware of)?
Would it be possible to do something like have the UI run as a separate process, and have it share some memory/communicate with the main process, using safe, simple rust?
p.s. I'm aware of this question, it's relevant but doesn't really answer my questions.
Why does MacOS/iOS enforce the GUI being on Thread 0.
Because it's been that way for over 30 years now (since NeXTSTEP), and changing it would break just about every program out there, since almost every Cocoa app assumes this, and relies on it regularly, not just for the main thread, but also the main runloop, the main dispatch group, and now the main actor. External UI events (which come from other processes like the window manager) are delivered on thread 0. NSDistributedNotifications are delivered on thread 0. Signal handling, the list goes on. Yes, it is certainly possible for Darwin (which underlies Cocoa) to be rewritten to allow this. That's not going to happen. I'm not sure what other answer you want.
Would it be possible to do something like have the UI run as a separate process, and have it share some memory/communicate with the main process, using safe, simple rust?
Absolutely. See XPC, which is explicitly for this purpose (communicating, not sharing memory; don't share memory, that's a mess). See sys-xpc for the Rust interface.

Multi-thread daata access issue, #synchronized & serial queue

As you may have experienced, access none-thread safe variables is a big headache. For iOS one simple solution is to use keyword #synchronized, which will add NSLock to insure the data can be accessed by unique one thread, the disadvantage is as below:
Lock too many will reduce app performance greatly, especially when invoked by main thread.
Dead lock will occur when logic becomes complex.
Based on the above considerations, we prefer to use serial queue to handle, each thread safe critical operation will append to the end of the queue, it is a great solution, but the problem is that all access interfaces should by designed in asyn style, see the following one.
-(id)objectForKey:(NSString *)key;
The people who invoke this class aren't reluctant to design in this way. Anyone who has experience on this field please share and discuss together.
The final solution is using NSUserDefault to store small data, for large cache data put them in file maintained by ourselves.
Per Apple doc the advantage of NSUserDefault is thread safe and will do synchronize work periodically.

How to lock an NSLock on a specific thread

I have a property #property NSLock *myLock
And I want to write two methods:
- (void) lock
and
- (void) unlock
These methods lock and unlock myLock respectively and they need to do this regardless of what thread or queue called them. For instance, thread A might have called lock but queue B might be the one calling unlock. Both of these methods should work appropriately without reporting that I am trying to unlock a lock from a different thread/queue that locked it. Additionally, they need to do this synchronously.
It is rare anymore that NSLock is the right tool for the job. There much better tools now, particularly with GCD; more later.
As you probably already know from the docs, but I'll repeat for those reading along:
Warning: The NSLock class uses POSIX threads to implement its locking behavior. When sending an unlock message to an NSLock object, you must be sure that message is sent from the same thread that sent the initial lock message. Unlocking a lock from a different thread can result in undefined behavior.
That's very hard to implement without deadlocking if you're trying to lock and unlock on different threads. The fundamental problem is that if lock blocks the thread, then there is no way for the subsequent unlock to ever run on that thread, and you can't unlock on a different thread. NSLock is not for this problem.
Rather than NSLock, you can implement the same patterns with dispatch_semaphore_create(). These can be safely updated on any thread you like. You can lock using dispatch_semaphore_wait() and you can unlock using dispatch_semaphore_signal(). That said, this still usually isn't the right answer.
Most resource contention is best managed with an operation queue or dispatch queue. These provide excellent ways to handle work in parallel, manage resources, wait on events, implement producer/consumer patterns, and otherwise do almost everything that you would have done with an NSLock or NSThread in the past. I highly recommend the Concurrency Programming Guide as an introduction to how to design with queues rather than locks.

Understanding Multithreading in iOS

I am trying to understand multi-threading on iOS in more detail. I went through some of the class references like NSThread, NSRunLoop, NSTask..
First of all as indicated on the following link:
use of runloop
Runloop runs within a Thread.
So why do we need to define our own Runloop in our app? In the case of NSThread it is useful because some of time-consuming processes can run in a separate thread so that the app will still be responsive on the main thread.
Interacting with the thread's run loop may be useful if you have a thread whose work you want to continue periodically. That is, a run loop would do some work, and then when it is finished with that work, it would put the thread to rest for some time, then resume work at a later time -- effectively preventing the thread from exiting. You won't need to interact with them or configure/create them yourself regularly (only a small percentage of apps would qualify, if you are using high level abstractions such as Foundation because Foundation would set them up on your behalf in most scenarios).
If your secondary thread just does a specified task and does not need to wait for some external event (e.g. a download to finish), you would (typically) not need to interact with the run loop.
You might consider looking at using NSOperationQueues, NSOperations and NSBlockOperations instead as these will manage themselves, will allow for cancellation of tasks and can be scheduled on main and background threads.

What exactly does a pthread mutex lock out?

I'm assuming this has been asked on here, but I can't find this particular question. Does it just lock the part of the code in between the lock and unlock, or does it lock global variables? Like for this code
pthread_mutex_lock(&mtx);
bitmap[index] = 1;
pthread_mutex_unlock(&mtx);
the mutex just locks that line of code? Is there a way to lock specific variables without just locking the part of code that uses them?
No, it locks the actual mutex variable.
Any piece of code that attempts to lock that mutex while it's locked will block until it's unlocked.
If that is the only piece of code that locks the mutex then, yes, you can say it just protects that line. But that's not necessarily the case.
A mutex is used to serialise access to a resource. Whether that resource is considered a line of code or (more likely in this case) the bitmap array is down to where the mutex is locked and unlocked.
Chances are you have a few different areas where the bitmap array is read or modified and you should probably ensure they're all protected by the mutex.
No there is no way to just lock a variable.
Mutex is just an abstraction. So whenever you want some variable should not be affected when you are working on it, declare a mutex for that variable and lock it as long as you want.
There is no direct relation between the mutex and the variable you want to lock. Its up to the programmer. Most commonly it is used in multi-threaded environment.
Whenever a variable (a resource. In programming, resources are manipulated in variables) is shared across parallel running processes (according to kernel, threads of a same process are a group of processes sharing same address space and some resources), if a programmer want to make the variable to be accessed exactly only one process at a particular time, he has to write the block of code accessing the variable in all the processes (or threads) between a mutex lock pair (pthread_mutex_lock and pthread_mutex_unlock). So whenever the variable is accessed in any process (or thread), mutex will be locked. So if another process want's to access the variable, it has to wait until the mutex unlock. So the programmers' final goal is achieved.

Resources