What is Ruby's ThreadGroup for? - ruby

I was flicking through the Pickaxe, looking for the documentation on Thread, and came across ThreadGroup.
The documentation describes what it does, but it doesn't explain what it's for.
Is a thread group related to a thread pool, which I assumed Ruby doesn't have?

New threads are created in their parent's ThreadGroup. You can use the ThreadGroup to organize the implicit tree structure given by the parent threads spawning other threads, and use the list instance method to get all threads which have not terminated yet, i.e. to define methods operating on all threads in the group.
Additionaly, you can use enclose to prohibit adding (or removing) threads to this group, if you run untrusted code and want to keep an eye on the threads it spawns.

Related

Ruby mutex vs. GIL

Does a Ruby mutex allow two threads to execute concurrently if one thread is waiting on blocking I/O?
This is my understanding of how the GIL works for MRI. I'm curious if there's any difference between a mutex and GIL?
Yes, this works. Only because of this, using threads in MRI is actually useful for many workloads, even though only a single thread can concurrently execute "code".
A common example is a web application such as a Rails app. Here, you can run multiple threads with e.g. Puma in a single process, each handling a single request. Since you often wait for the database here, a different thread can also execute. This works because the database adapter (e.g. mysql2 or pg) releases the GIL with a call to the database and re-acquires it once the reply arrives and is delivered up to the caller.
With a Mutex however, you are ensuring that a certain block of code is only executed by a single thread at a time. A common example is an adder:
class Adder
attr_reader :number
def initialize
#number = 0
end
def add(number)
new_number = #number
new_number = new_number + number
#number = new_number
# The above code is extremely verbose to show what's happening here.
# It is equivalent to
# #number += number
end
end
Here, the Adder#add method is not thread save. If multiple threads try to concurrently add numbers, some updates will be lost since the operation is not atomic (but consists of a read, an operation and a write). With a Mutex around add, you can ensure that the operation finishes in one thread and the shared data structures are updated consistently.
As a general advice, you should always use a Mutex if you are reading or updating any data shared across thread boundaries. To ensure correctness, you should also strictly control which data structures are passed across thread boundaries and avoid it if possible.
If you still need this, the concurrent-ruby gem provides some thread-safe data structures which can help with sharing data across thread-boundaries.
The Global Interpreter Lock on the default implementation (MRI) prevents any two Ruby threads from running concurrently. A Mutex prevents specific threads from running concurrently, where others are free to do whatever.
Note that the rules are different in implementations that do not have a GIL, like JRuby, where threads can run independently and concurrently.
In effect the Global Interpreter Lock is itself a mutex, but it's one that's engaged by default, not explicitly in your code, like with synchronize.
If a thread is blocked waiting on a mutex then other threads continue to run normally, they're able to do whatever they need independently.
The Global Interpreter Lock is also different in that your Ruby thread will be periodically interrupted so that other threads can run. This is to prevent one thread from monopolizing the lock.

MFC CEvent class member function SetEvent , difference with Thread Lock() function?

what i s the difference between SetEvent() and Thread Lock() function? anyone please help me
Events are used when you want to start/continue processing once a certain task is completed i.e. you want to wait until that event occurs. Other threads can inform the waiting thread about the completion of this task using SetEvent.
On the other hand, critical section is used when you want only one thread to execute a block of code at a time i.e. you want a set of instructions to be executed by one thread without any other thread changing the state at that time. For example, you are inserting an item into a linked list which involves multiple steps, at that time you don't want another thread to come and try to insert one more object into the list. So you block the other thread until first one finishes using critical sections.
Events can be used for inter-process communication, ie synchronising activity amongst different processes. They are typically used for 'signalling' the occurrence of an activity (e.g. file write has finished). More information on events:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686915%28v=vs.85%29.aspx
Critical sections can only be used within a process for synchronizing threads and use a basic lock/unlock concept. They are typically used to protect a resource from multi-threaded access (e.g. a variable). They are very cheap (in CPU terms) to use. The inter-process variant is called a Mutex in Windows. More info:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682530%28v=vs.85%29.aspx

PostThreadMessage usage across threads created in two c++ files

I have a thread created in the main function and PostThreadMessage from ther is invoked with the corresponding thread ID. If one more thread is created in a seperate file how can we invoke PostThreadMessage as we dont know the thread ID which is a parameter for invoking
You have to either:
Store/pass the thread ID (or thread handle) from whatever created the thread to whatever needs to know about the thread; or
Have some way to find the thread via an object it creates. (e.g. If it creates a window with a unique class, you could find that window and then ask the OS which thread owns the window.)
Other than that, there is no magical way to "find a particular thread with no known attributes that was created by another thread that didn't tell anyone about", unless you want to enumerate all threads within your process (but you would have no way to know thread was the right one, unless you did something like #1 or #2 above, and if you do either of them then you don't need to enumerate in the first place).
Note that there will almost always be more threads in your process than the ones you explicitly create, so you cannot just look for "any thread except the two I already know about," because you might pick up a system worker-thread or similar that you should not mess with.

Clarification on Threads and Run Loops In Cocoa

I'm trying to learn about threading and I'm thoroughly confused. I'm sure all the answers are there in the apple docs but I just found it really hard to breakdown and digest. Maybe somebody could clear a thing or 2 up for me.
1)performSelectorOnMainThread
Does the above simply register an event in the main run loop or is it somehow a new thread even though the method says "mainThread"? If the purpose of threads is to relieve processing on the main thread how does this help?
2) RunLoops
Is it true that if I want to create a completely seperate thread I use
"detachNewThreadSelector"? Does calling start on this initiate a default run loop for the thread that has been created? If so where do run loops come into it?
3) And Finally , I've seen examples using NSOperationQueue. Is it true to say that If you use performSelectorOnMainThread the threads are in a queue anyway so NSOperation is not needed?
4) Should I forget about all of this and just use the Grand Central Dispatch instead?
Run Loops
You can think of a Run Loop to be an event processing for-loop associated to a thread. This is provided by the system for every thread, but it's only run automatically for the main thread.
Note that running run loops and executing a thread are two distinct concepts. You can execute a thread without running a run loop, when you're just performing long calculations and you don't have to respond to various events.
If you want to respond to various events from a secondary thread, you retrieve the run loop associated to the thread by
[NSRunLoop currentRunLoop]
and run it. The events run loops can handle is called input sources. You can add input sources to a run-loop.
PerformSelector
performSelectorOnMainThread: adds the target and the selector to a special input source called performSelector input source. The run loop of the main thread dequeues that input source and handles the method call one by one, as part of its event processing loop.
NSOperation/NSOperationQueue
I think of NSOperation as a way to explicitly declare various tasks inside an app which takes some time but can be run mostly independently. It's easier to use than to detach the new thread yourself and maintain various things yourself, too. The main NSOperationQueue automatically maintains a set of background threads which it reuses, and run NSOperations in parallel.
So yes, if you just need to queue up operations in the main thread, you can do away with NSOperationQueue and just use performSelectorOnMainThread:, but that's not the main point of NSOperation.
GCD
GCD is a new infrastructure introduced in Snow Leopard. NSOperationQueue is now implemented on top of it.
It works at the level of functions / blocks. Feeding blocks to dispatch_async is extremely handy, but for a larger chunk of operations I prefer to use NSOperation, especially when that chunk is used from various places in an app.
Summary
You need to read Official Apple Doc! There are many informative blog posts on this point, too.
1)performSelectorOnMainThread
Does the above simply register an event in the main run loop …
You're asking about implementation details. Don't worry about how it works.
What it does is perform that selector on the main thread.
… or is it somehow a new thread even though the method says "mainThread"?
No.
If the purpose of threads is to relieve processing on the main thread how does this help?
It helps you when you need to do something on the main thread. A common example is updating your UI, which you should always do on the main thread.
There are other methods for doing things on new secondary threads, although NSOperationQueue and GCD are generally easier ways to do it.
2) RunLoops
Is it true that if I want to create a completely seperate thread I use "detachNewThreadSelector"?
That has nothing to do with run loops.
Yes, that is one way to start a new thread.
Does calling start on this initiate a default run loop for the thread that has been created?
No.
I don't know what you're “calling start on” here, anyway. detachNewThreadSelector: doesn't return anything, and it starts the thread immediately. I think you mixed this up with NSOperations (which you also don't start yourself—that's the queue's job).
If so where do run loops come into it?
Run loops just exist, one per thread. On the implementation side, they're probably lazily created upon demand.
3) And Finally , I've seen examples using NSOperationQueue. Is it true to say that If you use performSelectorOnMainThread the threads are in a queue anyway so NSOperation is not needed?
These two things are unrelated.
performSelectorOnMainThread: does exactly that: Performs the selector on the main thread.
NSOperations run on secondary threads, one per operation.
An operation queue determines the order in which the operations (and their threads) are started.
Threads themselves are not queued (except maybe by the scheduler, but that's part of the kernel, not your application). The operations are queued, and they are started in that order. Once started, their threads run in parallel.
4) Should I forget about all of this and just use the Grand Central Dispatch instead?
GCD is more or less the same set of concepts as operation queues. You won't understand one as long as you don't understand the other.
So what are all these things good for?
Run loops
Within a thread, a way to schedule things to happen. Some may be scheduled at a specific date (timers), others simply “whenever you get around to it” (sources). Most of these are zero-cost when idle, only consuming any CPU time when the thing happens (timer fires or source is signaled), which makes run loops a very efficient way to have several things going on at once without any threads.
You generally don't handle a run loop yourself when you create a scheduled timer; the timer adds itself to the run loop for you.
Threads
Threads enable multiple things to happen at the exact same time on different processors. Thing 1 can happen on thread A (on processor 1) while thing 2 happens on thread B (on processor 0).
This can be a problem. Multithreaded programming is a dance, and when two threads try to step in the same place, pain ensues. This is called contention, and most discussion of threaded programming is on the topic of how to avoid it.
NSOperationQueue and GCD
You have a thing you need done. That's an operation. You can't have it done on the main thread, or you'd simply send a message like normal; you need to run it in the background, on a secondary thread.
To achieve this, express it as either an NSOperation object (you create a subclass of NSOperation and instantiate it) or a block (or both), then add it to either an NSOperationQueue (NSOperations, including NSBlockOperation) or a dispatch queue (bare block).
GCD can be used to make things happen on the main thread, as well; you can create serial queues and add blocks to them. A serial queue, as its name suggests, will run exactly one block at a time, rather than running a bunch of them in parallel.
So what should I do?
I would not recommend creating threads directly. Use NSOperationQueue or GCD instead; they force you into better thinking habits that will reduce the risk of your threaded code inducing headaches.
For things that run periodically, not fitting into the “thing I need done” model of NSOperations and GCD blocks, consider just using the run loop on the main thread. Chances are, you don't need to put it on a thread after all. A rendering loop in a 3D game, for example, can be a simple timer.

What's the equivalent C# 'Thread.Join()' in Cocoa?

I'm making an iPhone app using threads.
I was used C# for a while, there was a method Thread.Join() which blocks current thread for specific thread completes execution. What's the equivalent in Cocoa for it? Or Alternatives?
---edit---
PS. I'm using NSThread.
---edit---
I'm finding a method like 'waitForThreadExit' which blocks caller thread until thread completes execution.
The threads created with Cocoa cannot be created as detached. NSThread instances always wrap attached POSIX threads for resource management reasons. As quoted in the Thread Programming Guide:
If you do want to create joinable
threads, the only way to do so is
using POSIX threads. POSIX creates
threads as joinable by default. To
mark a thread as detached or joinable,
modify the thread attributes using the
pthread_attr_setdetachstate function
prior to creating the thread. After
the thread begins, you can change a
joinable thread to a detached thread
by calling the pthread_detach
function. For more information about
these POSIX thread functions, see the
pthread man page. For information on
how to join with a thread, see the
pthread_join man page.
If you are looking for a way to be notified of the end of a NSThread, you can use the NSThreadWillExitNotification notification.
NSThread does not expose a Join method by any name. NSThread is a very simple, high level, wrapper class. It's very useful for doing threading in a GUI app as it simplifies calling back onto the main thread. For simple backgrounding of tasks and communicating the result back to the main thread on completion this should be sufficient and is fairly easy to get right. If you want to do more "advanced" things (and that includes Join, here) then you'll either have to go to pthreads or layer the semantics on top of NSThread (perhaps by using NSCondition).
If you are using pthreads, then use: pthread_join.
On the other hand, if you are using NSThread class, there is no equivalent to join method you are referring to.
You could try wiht NSObject's message performSelectorOnMainThread:withObject:waitUntilDone:
But I am not exactly sure what you are trying to accomplish here.
Here's is Apple's Multithreading Programming Guide.
You can do this yourself using NSConditionLock. Define two conditions: "running" and "terminated". The worker thread acquires the lock "running" and upon termination it unlocks with condition "terminated". A join would then be to acquire the lock "terminated" and then unlock it "terminated".

Resources