Implementing Semaphores, locks and condition variables - c++

I wanted to know how to go about implementing semaphores, locks and condition variables in C/C++. I am learning OS concepts but want to get around implementing the concepts in C.
Any tutorials?

Semaphores, locks, condition variables etc. are operating system concepts and must typically be implemented in terms of features of the operating system kernel. It is therefore not generally possible to study them in isolation - you need to consider the kernel code too. Probably the best way of doing this is to take a look at the Linux Kernel, with the help of a book such as Understanding The Linux Kernel.

Semaphore at the very simplest is just a counter you can add and subtract from with a single atomic operation. Wikipedia has an easy to understand explanation that pretty much covers your question about them:
http://en.wikipedia.org/wiki/Semaphore_(programming)

A good starting point for learning OS concepts is probably Andrew Tanenbaum's "Modern Operating Systems". He also has another book on his own OS (Minix), which is called "Operating Systems: Design and Implementation" which goes more into detail about coding. You should be able to find those books in your local library.
Related topics you might want to look up to get the grip on how and why to use semaphores: race conditions, synchronization, multithreading, consumer-producer-problem.

At the ground level, if you want to implement that sort of thing, you're going to need to use assembly language. C and C++ simply don't expose the sort of features necessary to write concurrent code --- except by using libraries, which use assembler in their implementation.

The minix stuff is pretty good. A simpler example is the MicroC/OS stuff. It comes with a textbook that goes into good detail, all the source is there. It has the basic elements there and the code is small enough that you can understand it in a relatively short period of time.
http://www.micrium.com/products/rtos/kernel/rtos.html
http://en.wikipedia.org/wiki/MicroC/OS-II
Another thing you can do, is make a faked out OS in an application on linux. I did this by setting up the basic tick with an itimer, then swapping threads around with the function call swapcontext (man 2 swapcontext) which will save the regs on the stack. That gets the ugly stuff out of the way and you are left to implement the semaphores/mutexes/timers and all that. It was quite fun.
Despite what some of the posts say, assembler is not required. A knowledge of it will always help. It never hurts to understand how the internals/complilers/etc work when you are writing even high level applications.

For basic understanding, you can refer book Operating System Concepts, by Avi Silberschatz, Peter Baer Galvin, Greg Gagne and is really good.
You can also visit Dave Marshall's site for some support. Refer Semaphore section there.

Funny, Stevens Book is one of the classic texts for describing the use of synchronisation primitives and their uses. He certainly seems to think they can be used to control inter process communication. I tend to agree with him. Networking, no, IPC yes. most certainly yes.

You can catch up with alot of IPC( Inter Process Communication) Books, that can explain the ins and outs of what you need. There is one classic book. Unix Network Programming Inter Process Communication by Richard Stevens. you will get all you need. :)

Related

C++ synchronization guidelines

Does anyone know of a decent reference for synchronization issues in C++? I'm thinking of something similar to the C++ FAQ lite (and the FQA lite) but with regards to concurrency, locking, threading, performance issues, guidelines, when locks are needed and when they aren't, dealing with multithreaded library code that you can't control, etc. I don't care about the inner issues of how different lock types can be implemented etc, I just use boost for that.
I'm sure there are a lot of good books out there, I'd prefer something (preferably online) that I can use as a goto for when a question or an issue pops up in my mind. I'm not really a beginner to this all so I would like a concise reference for all those different types of situations that can popup when writing multithreaded libraries that use other multithreaded libraries.
Like:
When is it better to have one big lock protecting a bunch of data vs a bunch of smaller locks protecting each piece of data? (what are the costs associated with having lots of locks? Resource acquisition costs? Locking time performance costs?)
What's the performance hit of pushing something onto a queue and having another thread pop the queue vs dealing that that data in the original thread?
Are there any simple idioms to make sure things just work when you're not so concerned about performance?
Anyway, I just want to know if there are any decent references out there that people use.
I'd recommend two resources:
Herb Sutter's Effective Concurrency articles
Anthony Williams's C++ Concurrency In Action (not yet published, but available as a PDF)

When knowledge of "multithreading" is specified in a C++ job description, what is the expectation?

I understand it should cover threading primitives (mutex, semaphore, condition variables etc.) plus design patterns (such as those specified in POSA2). But what's more? Every project has its own multithreading scenarios and one may have not dealt with those that the job is expecting?. So how does one build their knowledge and prove that they have the ability?
Regardless of specifics solid, detailed and very deep knowledge is required. One should understand how the bottlenecks form, how to deal with scalability problems, how to diagnose cases where synchronization is required but is erroneously omitted.
If for example you had a job experience with multithreading and I ran an interview to assess you I'd ask detailed questions on typical scenarios that arise when developing multithreaded programs. I wouldn't expect you knew many technologies or some specific technology, but I'd expect you to have mastered the technology you claim you're familiar with in great detail and to understand which fundamental problems it solves and how.
I would expect the candidate has knowledge and experience of the issues that arise when multiple threads access shared resources. What problems can be caused by concurrent access and what problems the solutions (such as locking etc) present.
At the very least understanding of how to write and read asych code on the platform of choice.
After this it will be understanding the specifics if the platform - e.g. such how to access the primary window in windows system while many things needs up the display at the same time.
Fundamentally is about understanding what trade-offs are needed and when.
May I present a different view. I think you should understand the basics,
but really never give up on a job based on a flyer description. I have
not met a programming concept that could not be figured out in half a day.
So, basically, read a tutorial before the interview, do not try to misrepresent
your actual experience with threading, but make sure they know the things you
had more hands on experience, and see if there is a mutual interest in you working
for the company. They may like you even if you know nothing about threading if they are confident that you can pick it up at full speed.

Linux IPC - Multiple writers, single reader

I have never written any IPC C++ on Linux before.
My problem is that I will have multiple clients (writers), and a single server (reader). All of these will be on the same machine. The writers will deliver chunks of data (a string/struct) to the reader. The reader will then read them in FIFO and do something with them.
The types of IPC on Linux are either Pipes or Sockets/Message Queues as far as I can tell.
I was just wondering if someone could recommend me a path to go down. I'm leaning towards sockets, but I have no real basis for that. Is there anything I should read/understand before embarking on this journey?
Thanks
The main issue you should consider is what kind of data you are passing as this will in part determine your options. This comes down to whether your data is bounded or not. If it isn't bounded then something stream oriented like FIFOs or sockets are appropriate; if it is then you might make better use of of things like MQs or shared memory. Since you mention both strings and structs it is hard to say what is appropriate in your case, though if your strings are bounded within some reasonable maximum you can use anything with some minor fiddling.
The second is speed. There is never a completely correct answer for this but generally it goes something like: shared memory, MQs, FiFOs, domain sockets, network sockets.
The third is ease of use. Shared memory is the biggest PITA since you have to handle your own synchronization. Pipes are easy so long as your message lengths stay below PIPE_BUF size. The OS handles most of your headaches with MQs. Sockets are easy enough but you have the setup boilerplate.
Lastly several of the IPC mechanisms have both POSIX and SYSV variants. Generally POSIX is the way to go unless the SYSV type has some feature you really need or want.
EDIT: Count0's answer reminded me that you might be interested in something more abstract and higher level. In addition to ACE you can look at Poco. And, of course, no SO answer is complete if it doesn't mention Boost somewhere.
System V IPC is somewhat fiddly to use but it is a mature, robust technology. Message queues would probably do what you want and support atomic queuing/de-queuing.
Sockets are easy to use and also support communication over a network. However, they do not do any queuing, so you would have to write the queue management code within your server. Using sockets with C++ is not vastly different to using them with C. There are plenty of guides to this on the net and books such as Stevens' 'Unix Network Programming (vol 1)' that cover this topic in some depth.
A good place to get your feet wet is this sockets tutorial.
You'll then need to bone-up on threads & mutexes and here.
With the above you're all set to start playing ;-)
Though you've not asked for books, and because the answers above are so good, I'm only going to suggest you get your hands on copies of these two tomes:
UNIX Network Programming, Volume 2, Second Edition: Interprocess Communications, W. Richard Stevens
Advanced Programming in the UNIX Environment, Second Edition, W. Richard Stevens and Stephen A. Rago
There are inevitable ins & outs with this kind of coding, these two books will help you through whatever confusion you encounter.
Try to take a look at ACE (Adaptive Communication Environment). The ACE libraries are free available, very mature and cross platform. Unfortunately a good documentation is not, i would recommend this book to look for a good solution. You might try to take a look at this tutorial to get a feel of the patterns (at the end of the document). ACE uses a bunch of patterns to deal very successfully and efficient with those problems especially in a networked context, so it should be a good start to scope for good patterns and methods to use.
Especially Ace_Task using the Message_Queue allow to do what you need.

can one make concurrent scalable reliable programs in C as in erlang?

a theoretical question. After reading Armstrongs 'programming erlang' book I was wondering the following:
It will take some time to learn Erlang. Let alone master it. It really is fundamentally different in a lot of respects.
So my question: Is it possible to write 'like erlang' or with some 'erlang like framework', which given that you take care not to create functions with sideffects, you can create scaleable reliable apps as well as in Erlang? Maybe with the same msgs sending, loads of 'mini processes' paradigm.
The advantage would be to not throw all your accumulated C/C++ knowledge over the fence.
Any thoughts about this would be welcome
Yes, it is possible, but...
Probably the best answer for this question is given by Robert Virding’s First Rule:
“Any sufficiently complicated
concurrent program in another language
contains an ad hoc,
informally-specified, bug-ridden, slow
implementation of half of Erlang.”
Very good rule is use the right tool for the task. Erlang excels in concurrency and reliability. C/C++ was not designed with these properties in mind.
If you don't want to throw away your C/C++ knowledge and experience and your project allows this kind of division, good approach is to create a mixed solution. Write concurrent, communication and error handling code in Erlang, then add C/C++ parts, which will do CPU and IO bound stuff.
You clearly can - the Erlang/OTP system is largely written in C (and Erlang). The question is 'why would you want to?'
In 'ye olde days' people used to write their own operating system - but why would you want to?
If you elect to use an operating system your unwritten software has certain properties - it can persist to hard disk, it can speak to a network, it can draw on screens, it can run from the command line, it can be invoked in batch mode, etc, etc...
The Erlang/OTP system is 1.5M lines of code which has been demonstrated to give 99.9999999% uptime in large systems (the UK phone system) - that's 31ms downtime a year.
With Erlang/OTP your unwritten software has high reliability, it can hot-swap itself, your unwritten application can failover when a physical computer dies.
Why would you want to rewrite that functionality?
I would break this into 2 questions
Can you write concurrent, scalable C++ applications
Yes. It's certainly possible to create the low level constructs needed in order to achieve this.
Would you want to write concurrent, scalable, C++ applications
Perhaps. But if I was going for a highly concurrent application, I would choose a language that was either designed to fill that void or easily lent itself to doing so (Erlang, F# and possibly C#).
C++ was not designed to build highly concurrent applications. But it can certainly be tweaked into doing so. The cost might be higher than you expect though once you factor in memory management.
Yes, but you will be doing some extra work.
Regarding side effects, consider how the .net/plinq team is approaching. Plinq won't be able to enforce you hand it stuff with no side effects, but it will assume you do so and play by its rules so we get to use a simpler api. Even if the language doesn't have built-in support for it, it will still simplify things as you can break the operations more easily.
What I can do in one Turing complete language I can do in any other Turing complete language.
So I interpret your question to read, is it as easy to write a reliable and scalable application in C++ as it is in Erlang?
The answer to that is highly subjective. For me it is easier to write it in C++ for the following reasons:
I have already done it in C++ (at least three times).
I don't know Erlang.
I have read a great deal about Stackless Python, which feels to me like a highly concurrent message based cooperative multitasking system in python, but of course python is written on top of C.
Having said that. If you already know both languages, and you have the problem well defined, you can then make the best choice based on all the information you have at hand.
the main 'problem' with C (or C++) for writing reliable and easy to extend programs is that in C you can do anything. so, the first step would be to write a simple framework that restricts just a bit. most good programmers do that anyway.
in this case, the restrictions would be mostly to make it easy to define a 'process' within whatever level of isolation you want. fork() has a reputation of being slow, and threads also need significant time to spawn, so you might want to use a cooperative multitasking, which can be far more efficient, and you could even make it preemptive (i think that's what Erlang does). to get multi-core efficiency, set a pool of threads and make all of them complete to run the tasks.
another important part would be to create an appropriate library of immutable data structures, so that using them (instead of the standard lib) your functions would be (mostly) side-effect-free.
then it's just a matter of setting a good API for message passing and futures... not easy, but at least it doesn't seem like changing the language itself.

Which concurrent programming concepts do hiring managers expect developers to understand?

When I hire developers for general mid-to-senior web app development positions, I generally expect them to understand core concurrent programming concepts such as liveness vs. safety, race conditions, thread synchronization and deadlocks. I'm not sure whether to consider topics like fork/join, wait/notify, lock ordering, memory model basics (just the basics) and so forth to be part of what every reasonably seasoned developer ought to know, or whether these are topics that are more for semi-specialists (i.e. developers who have made a conscious decision to know more than the average developer about concurrent programming).
I'd be curious to hear your thoughts.
I tend to think that at this point in time concurrent programming at any serious level of depth is still a specialist skill. Many will claim to know about it through study, but many will also make an almighty mess of it when they come to apply it.
In addition to the considerations listed, I would also look at resource implications and the various overheads of using processes, threads and fibers. In some contexts, e.g. mobile devices, excessive multithreading can have serious performance implications. This can lead to portability issues with multithreaded code.
I guess if I was interviewing a candidate in this situation, I would work with a real world example rather than hitting on more general topics which can be quoted back verbatim from a text book. I say this having done a fair bit of multithreaded work myself and remembering how badly I screwed up the first couple of times. Many can talk the talk... ;)
I know all these topics, but I studied them. I also know many competent senior programmers that don't know these. So unless you expect these programmers to be using those concepts actively, there is no reason to turn down a perfectly good candidate because they don't understand every aspect of concurrency
The real question is:
In what ways does it matter to the code they will be developing?
You should know which concepts the development position you're hiring for needs to know to be able to work on the projects that they will be responsible for.
As with anything in the programming world.. The devil is in the details, and you can't know everything. Would you expect them to know Perl if you were hiring for a Java position?
Also, concurrency, at this stage, while well described in generalized theory, is heavily implementation and platform dependent. Concurrency in Perl on an AIX box is not the same game as concurrency in a C++ Winforms app. They can have all the theory in the world under their belts, but if it's required for the job, then they should have intimate knowledge of the platform they are expected to use it on as well.
I interview folks for concurrency-related positions frequently and I look for three general aspects:
General understanding of core concepts like the ones you list (language-independent)
Specific understanding of Java concurrency libraries and primitives (specific to the work they'd be doing)
Ability to design the solution to a concurrent problem in a reasonable way.
I consider #1 a requirement (for my positions). I consider #2 a nice to have. If they understand it and can describe it in terms of pthreads or whatever other library, it's no biggie to learn the latest Java concurrency libraries (the concepts are the hard part). And #3 tends to separate the hires from the maybe-hires.
Per your question, I wouldn't consider fork/join to be known by almost anyone, esp someone applying for a web app developer position. I would look for developers to have experience with some (but not all) of those topics. Most developers I've interviewed have not used the Java 5+ concurrency libs at all but they can typically describe things like data race or deadlock.