isocpp / isocpp/CppCoreGuidelines

An idea for the GSL to make multithreading code safer.

Open
#924 13 comments 1 reaction 1 assignee View on GitHub

@lbrandy is already working on this.

Since May 15, 2017.

Dominant language
CSS
Stars
45.3k
Forks
5.6k
PR merge metrics
No merged PRs in 30d

Description

I have what I think maybe (or may not be lol) a potential candidate for the GSL.

The basic idea is very simple. There are just a few wrapper classes used to enforce read/write locking and, at the same time, presenting either a const (for read-only) or non-const (for read-write) view of the wrapped object.

The idea is to make it compile-time impossible to improperly access a resource shared between threads.

The read-only version (readable_lock) contains an internal shared_lock and binds a const reference (const&) to the target object ensuring that only const functions can be invoked.

The read_write version (writable_lock) contains an internal unique_lock and a non-const reference (&) to the target allowing updates to its internal state.

Here is some example usage:

lockable<std::vector<int>> v;          // lockable vector wrapper

v.push_back(3);                        // compile error

std::cout << v.size() << '\n';         // compile error

// locks are released at the end of their scope
{
	auto ro_v = v.lock_for_reading();  // read-only locked wrapper

	ro_v->push_back(3);                // compile error

	std::cout << ro_v->size() << '\n'; // OK! (const functions accessible)
}

{
	auto rw_v = v.lock_for_writing();  // read-or-write locked wrapper
	
	rw_v->push_back(3);                // OK! (non const functions accessible)
	
	std::cout << rw_v->size() << '\n'; // OK! (const functions accessible)
}

lockable<std::size_t> i{0};            // lockable integer wrapper

{
	auto [ro_v, rw_i] = lock(for_reading(v), for_writing(i));   // deadlock safe locking
	
	ro_v->push_back(*rw_i);            // compile error (ro_v is read only)
	
	*rw_i = ro_v->size();              // OK!
}

Does this sound like a useful addition to the library?

To be honest I am not even sure of the practicality as I have not used this technique in an actual project. But on paper, to me at least, it looks like it could be quite useful.

I have a preliminary working version for the above code. However my template meta-programming skills are not the best so it is possible/likely I have missed a lot of tricks and gotchas. Also, there are some crucial features yet to be implemented (like copy/move semantics).

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.