Is the objc_msgSend function thread-safe? - ios

Is the objc_msgSend function thread-safe?
Check the source code and find that it is written in assembly, but it is not locked at the beginning of the function. Will it not cause confusion when called by multiple threads?

The details of this answer depend on the specifics of what you mean by "thread-safe", but for most definitions of "thread-safe" (e.g., calling this code from multiple threads will leave your program in a consistent state without unintended interactions), then the answer is yes, objc_msgSend is thread-safe.
The specifics of how this is done are complex, but some context:
A function is inherently thread-safe if it does not modify state shared across threads in a way that could lead to unintended consequences
For example,
func add(_ a: Int, _ b: Int) -> Int {
a + b
}
is inherently thread-safe — you can't call it in a way that would cause it to mutate shared state somehow
A function is thread-safe if it does modify state shared across threads, but in a way that is coordinated with other threads reading that state
objc_msgSend falls into the latter camp: there are cases in which it does need to modify shared state (entries in the method cache), but it does so in a coordinated way.
Some helpful references, written by Mike Ash (who last I knew, was still working on the Obj-C runtime at Apple):
Friday Q&A 2017-06-30: Dissecting objc_msgSend on ARM64
Friday Q&A 2015-05-29: Concurrent Memory Deallocation in the Objective-C Runtime
objc_msgSend's New Prototype
In "Dissecting objc_msgSend on ARM64", Mike goes through the specifics of how objc_msgSend works, line-by-line. While the code has changed a bit since 2017, the specifics are all largely the same:
It gets the class of the target object passed in
It finds the method cache for that class
It uses the selector called on the target object to look up a method implementation for that method in the cache
If a method is not found in the cache, it falls back to looking it up, and possibly inserts it into the cache
It calls the implementation of that method directly
Of these operations, (1), (2), and (4) are most obviously thread-safe: (1) and (4) are inherently thread-safe (and don't rely on other threads at all), and (2) performs an atomic read that is safe across threads.
(3) is the trickier operation, since the method cache is shared for all instances of a class, and if you're calling a method on multiple instances of the same class at the same time, they might be digging through the method cache simultaneously. "Concurrent Memory Deallocation in the Objective-C Runtime" goes into this a little bit more on how this is done, but the general gist is that there are plenty of cool synchronization tricks that you can without needing to lock across threads. The full explanation is out of scope (and the article goes into a lot of detail anyway), but in a comment on "Dissecting objc_msgSend on ARM64" from Blaine Garst (one of the original authors of many of the features you might recognize as part of the Objective-C runtime):
Mike, you missed explaining the greatest secret of the messenger, one that Matt and Dave and I cooked up on the black couches at Seaport: how it is that multiple clients can read a mutable hash table without synchronization. It stumps people to this day. The answer is that the messenger uses a specialized garbage collector! I had put locks in when we first tried to do multi-threaded ObjC and it was miserable and then I read a paper by David Black where the kernel would reset the PC back to the start of a critical range for a mutex, and, well, we use the absense of a PC in critical ranges to deduce safety of reclaiming stale caches.
So, this operation is coordinated across threads too.
All of the work that objc_msgSend does is safe across thread boundaries, so much so that you can call methods on the same exact object across any number of threads at the exact same time, and it will work just fine. (Whether the implementation of the method is thread-safe is something else entirely.)
And in the end, it has to be. objc_msgSend is the backbone of pretty much all of Objective-C. If it wasn't thread-safe, it would be impossible to write multi-threaded Objective-C code. But luckily it is, and you can rely on it working at scale.

Related

Alternatives to pervasive use of the #synchronized directive on mutable array access

I am designing a singleton class in Objective-C which will be accessed by multiple threads. There are 3-4 NSMutableArrays in my class, outside classes have access with read, add and remove operations which is of course wrapped in this class.
As NSMutableArray is not thread safe, I am using #synchronized() to make my operations thread safe, however it causes too much usage of #synchronized() blocks.
Because for 3-4 array for each I have at least 1 add function, 1 remove function and 5 times I need to read the values. So, for 1 array I am using at least 7 #synchronized() blocks.
For 4 arrays, I need to add 28 #synchronized blocks in my singleton class.
Is there any better way to approach my problem?
or, If I do use too all these #synchronized directives, will it causes problem ?
I know that if I want to make my objects thread safe it will slow down my code, but besides that is there any drawback?
Typically it is not sufficient to just synchronize the primitive calls (CRUD) to gain thread safety. This fine granular level is just the basic, but you'll also have to think on a more global level and "atomize" larger amounts of code. How to do this is highly dependend on your actual implementation. Multithreading is evil(tm) and demands a comprehensive view, so there is no general answer for this.
Synchronized blocks will typically slow down your application, at least if they are called too frequently. Sometimes it's better to group multiple calls in one synchronized block, to avoid the locking overhead. Or you could use spin locks, if the calls are very short, to prevent unnecessary task suspensions (see here for an old question/answer).
For more details you can just consult the Apple documentation.

NSOperation, start vs main

According to Apple document on NSOperation, we have to override main method for non-concurrent operations and start method for concurrent operations. But why?
First, keep in mind that "concurrent" and "non-concurrent" have somewhat specialized meanings in NSOperation that tend to confuse people (and are used synonymously with "asynchronous/synchronous"). "Concurrent" means "the operation will manage its own concurrency and state." "Non-concurrent" means "the operation expects something else, usually a queue, to manage its concurrency, and wants default state handling."
start does all the default state handling. Part of that is that it sets isExecuting, then calls main and when main returns, it clears isExecuting and sets isFinished. Since you're handling your own state, you don't want that (you don't want exiting main to finish the operation). So you need to implement your own start and not call super. Now, you could still have a main method if you wanted, but since you're already overriding start (and that's the thing the calls main), most people just put all the code in start.
As a general rule, don't use concurrent operations. They are seldom what you mean. They definitely don't mean "things that run in the background." Both kinds of operations can run in the background (and neither has to run in the background). The question is whether you want default system behavior (non-concurrent), or whether you want to handle everything yourself (concurrent).
If your idea of handling it yourself is "spin up an NSThread," you're almost certainly doing it wrong (unless you're doing this to interface with a C/C++ library that requires it). If it's creating a queue, you're probably doing it wrong (NSOperation has all kinds of features to avoid this). If it's almost anything that looks like "manually handling doing things in the background," you're probably doing it wrong. The default (non-concurrent) behavior is almost certainly better than what you're going to do.
Where concurrent operations can be helpful is in cases that the API you're using already handles concurrency for you. A non-concurrent operation ends when main returns. So what if your operation wraps an async thing like NSURLConnection? One way to handle that is to use a dispatch group and then call dispatch_wait at the end of your main so it doesn't return until everything's done. That's ok. I do it all the time. But it blocks a thread that wouldn't otherwise be blocked, which wastes some resources and in some elaborate corner cases could lead to deadlock (really elaborate. Apple claims it's possible and they've seen it, but I've never been able to get it to happen even on purpose).
So another way you could do it is to define yourself as a concurrent operation, and set isFinished by hand in your NSURLConnection delegate methods. Similar situations happen if you're wrapping other async interfaces like Dispatch I/O, and concurrent operations can be more efficient for that.
(In theory, concurrent operations can also be useful when you want to run an operation without using a queue. I can kind of imagine some very convoluted cases where this makes sense, but it's a stretch, and if you're in that boat, I assume you know what you're doing.)
But if you have any question at all, just use the default non-conurrent behavior. You can almost always get the behavior you want that way with little hassle (especially if you use a dispatch group), and then you don't have to wrap your brain around the somewhat confusing explanation of "concurrent" in the docs.
I would assume that concurrent vs. non-concurrent is not just a flag somewhere but a very substantial difference. By having two different methods, it is made absolutely sure that you don't use a concurrent operation where you should use a non-concurrent one or vice versa.
If you get it wrong, your code will absolutely not work because of this design. That's what you want, because you immediately fix it. If there was one method only, then using concurrent instead of non-concurrent would lead to very subtle errors that might be very hard to find. And non-concurrent instead of concurrent will lead to performance problems that you also might miss.

proper threadpool using pthreads

I am trying to write a customized threadpool suited to my purpose using pthreads, and I am new to pthreads. I read these (POSIX threads programming and Linux Tutorial Posix Threads) tutorials online and they were quite helpful, but i still have some (maybe silly) doubts regarding mutexes and condition variables:
What is the scope of a mutex? Will a global mutex lock all the global variables so that only one thread can access them at a time? If i have two global mutexes, would they lock the same set of variables? What about a mutex that is declared inside a class or a function, what will happen when i lock/unlock it?
If i just plan to just read a global variable, and not modify it at all, should i still use a mutex lock?
If i am correct, a condition variable is used to wake up other threads which are sleeping (or blocked using pthread_cond_wait()) on some condition. The wake up call to sleeping threads is given by pthread_cond_signal() or pthread_cond_broadcast() from some other thread. How is the flow of control supposed to occur so that some all or one thread wake(s) up to do a work and wait until next work is available? I am particularly interested in a scenario with 4 threads.
Is there a way to set the affinity of a thread to a particular processor core before it is created (so that it starts execution on the desired core and no shifting of cores occur after creation)?
I am sorry if the questions look silly, but as i said, i am new to this. Any help, comments, code or pointer to good resources is appreciated. thanks in advance for your help.
That's a lot of questions. A few answers.
(1a) The scope of a mutex is whatever you program it to be. In that sense it is no different from any other kind of variable.
(1b) A global mutex will protect whatever variables you program it to protect. I think from your other questions you might have a fundamental misunderstanding here. There is nothing magical about mutexes. You can't just declare one and say "Ok, protect these variables", you have to incorporate the mutex in your code. So if you have two functions that use variable X and one does a mutex lock/unlock around any changes to the variable and the other function completely ignores that a mutex even exists you really aren't protecting anything. The best example I can think of is advisory file locks - one program can use them but if another doesn't then that file isn't locked.
(1c) As a rule, don't have multiple mutexes locking the same data. It is an invitation to problems. Again the use of mutexes depends on programmed cooperation. If function A is protecting data B with mutex C while function D is protecting data B with mutex E then data B isn't protected at all. Function A can hold the lock on mutex C but since function D pays no attention to it it will just overwrite data B anyway.
(1d) Basic scoping rules apply.
(2) No. If the variable isn't going to change in any way that would make it inconsistent among threads then you don't need to lock it.
(3) There are a number of detailed answers on this on SO that go into considerable detail on this. Search around a bit.
(4) Not that I am aware.

Check if pthread thread is blocking

Here's the situation, I have a thread running that is partially controlled by code that I don't own. I started the thread so I have it's thread id but then I passed it off to some other code. I need to be able to tell if that other code has currently caused the thread to block from another thread that I am in control of. Is there are way to do this in pthreads? I think I'm looking for something equivalent to the getState() method in Java's Thread class (http://download.oracle.com/javase/6/docs/api/java/lang/Thread.html#getState() ).
--------------Edit-----------------
It's ok if the solution is platform dependent. I've already found a solution for linux using the /proc file system.
You could write wrappers for some of the pthreads functions, which would simply update some state information before/after calling the original functions. That would allow you to keep track of which threads are running, when they're acquiring or holding mutexes (and which ones), when they're waiting on which condition variables, and so on.
Of course, this only tells you when they're blocked on pthreads synchronization objects -- it won't tell you when they're blocking on something else.
Before you hand the thread off to some other code, set a flag protected by a mutex. When the thread returns from the code you don't control, clear the flag protected by the mutex. You can then check, from wherever you need to, whether the thread is in the code you don't control.
From outside the code, there is no distinction between blocked and not-blocked. If you literally checked the state of the thread, you would get nonsensical results.
For example, consider two library implementations.
A: We do all the work in the calling thread.
B: We dispatch a worker thread to do the work. The calling thread blocks until the worker is done.
In both cases A and B the code you don't control is equally making forward progress. Your 'getstate' idea would provide different results. So it's not what you want.

Clone a lua state

Recently, I have encountered many difficulties when I was developing using C++ and Lua. My situation is: for some reason, there can be thousands of Lua-states in my C++ program. But these states should be same just after initialization. Of course, I can do luaL_loadlibs() and lua_loadfile() for each state, but that is pretty heavy(in fact, it takes a rather long time for me even just initial one state). So, I am wondering the following schema: What about keeping a separate Lua-state(the only state that has to be initialized) which is then cloned for other Lua-states, is that possible?
When I started with Lua, like you I once wrote a program with thousands of states, had the same problem and thoughts, until I realized I was doing it totally wrong :)
Lua has coroutines and threads, you need to use these features to do what you need. They can be a bit tricky at first but you should be able to understand them in a few days, it'll be well worth your time.
take a look to the following lua API call I think it is what you exactly need.
lua_State *lua_newthread (lua_State *L);
This creates a new thread, pushes it on the stack, and returns a pointer to a lua_State that represents this new thread. The new thread returned by this function shares with the original thread its global environment, but has an independent execution stack.
There is no explicit function to close or to destroy a thread. Threads are subject to garbage collection, like any Lua object.
Unfortunately, no.
You could try Pluto to serialize the whole state. It does work pretty well, but in most cases it costs roughly the same time as normal initialization.
I think it will be hard to do exactly what you're requesting here given that just copying the state would have internal references as well as potentially pointers to external data. One would need to reconstruct those internal references in order to not just have multiple states pointing to the clone source.
You could serialize out the state after one starts up and then load that into subsequent states. If initialization is really expensive, this might be worth it.
I think the closest thing to doing what you want that would be relatively easy would be to put the states in different processes by initializing one state and then forking, however your operating system supports it:
http://en.wikipedia.org/wiki/Fork_(operating_system)
If you want something available from within Lua, you could try something like this:
How do you construct a read-write pipe with lua?

Resources