Skip to content
This repository has been archived by the owner on Jun 16, 2024. It is now read-only.

anj1/ago

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

This is a thread pool implementation. There is no penalty to launching additional jobs, and you can have many more jobs than the OS is comfortable with.

For a quick example on how to use this, see ago_test.c.

I am aware that there are multiple implementations out there that try to do this. Mine is different, however:

- It's lightweight, providing only the base functionality needed for goroutine-like functions. There is no message passing, just function creation. I might add message-passing in the future.

- It's so lightweight you can (and should) directly include the source, without compiling a separate library.

- It is all POSIX threads so it's portable. There are no busy-wait loops or anything. If you don't have unistd.h on your system, just define NO_UNISTD. It might end up using more cpu, though.

- I took great care for there to be no race conditions or deadlocks, but with multithreading you never really know. Please tell me about any bugs you find.

By the way, the reason there's an alib_ before everything is that this was originally part of my own custom C extension library, Alib. I might release the full library in the future.

FAQ

Q. I found a bug in your program?

A. My email address is my username (at gmail.com).

Q. Why did you write this? What use is it?

A. Mainly for fun. Of course, I use it all the time in my own little projects, and you are more than welcome to.

Q. What's with all the synchronization? Can't you make it so that less primitives are needed?

A. Even experienced programmers sometimes underestimate the number of synchronization primitives required to implement even the most basic multithreaded apps. This invariably results in lots of grief when the program has erratic bugs and deadlocks that are hard to isolate and debug. The code is designed so that the mutexes are usually free before they are expected to be used. I've tested it extensively.

There might be a way to cut down on the number of synchronization primitives in the code. However, it would almost surely increase the code complexity, add more global variables, and not have any measurable effect on speed. As it currently stands, the code is incredibly fast, with alib_go() being virtually instantaneous even in the worst-case scenario.

Q. Why use global variables? Why is there only one thread pool?

A. Encapsulating threads in a struct or class would complicate the code and make little sense if you think about it. Threads are a global resource (just like I/O) and the ability to hide them from view would be dangerous. Few programming languages that implement lightweight threads offer more than one thread pool.

However, there might be some cases where this would be necessary. Andrew Gascoyne-Cecil has written a port of this repo to C++ that encapsulates the thread pool in a struct. See https://github.com/acecil/ago .

About

Portable thread pool implementation for C.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages