Multi threading in bf(C++) starts off with objects of the class
hi(thread)tt(std::thread). Each object of this class handles a separate
thread.

Before using tt(Thread) objects the tthi(thread) header file must be included.

Thread objects can be constructed in various ways:
    itemization(
    ittq(thread() noexcept)
       (The default constructor creates a tt(thread) object. As it receives no
function to execute, it does not start a separate thread of execution. It is
used, e.g., as a data member of a class, allowing class objects to start a
separate thread at some later point in time;)

    ittq(thread(thread &&tmp) noexcept)
       (The move constructor takes ownership of the thread controlled by
tt(tmp), while tt(tmp), if it runs a thread, loses control over its
thread. Following this, tt(tmp) is in its default state, and the newly created
thread is responsible for calling, e.g., tt(join).)

    ittq(explicit thread(Fun &&fun, Args &&...args))
       (This em(member template) (cf. section ref(MEMTEMP)) expects a function
(or functor) as its first argument. The function is immediately started as a
separate thread. If the function (or functor) expects arguments, then these
arguments can be passed to the tt(thread's) constructor immediately following
its first (function) argument. Additional arguments are passed with their
proper types and values to tt(fun). Following the tt(thread) object's
construction, a separately running thread of execution is started.

The notation tt(Arg &&...args) indicates that any additional arguments are
passed as is to the function. The types of the arguments that are passed to
the tt(thread) constructor and that are expected by the called function must
match: values must be values, references must be reference, r-value references
must be r-value references (or move construction must be supported). The
following example illustrates this requirement:
    verbinclude(-ans4 examples/threadargs.cc)
    itemization(
    it() At lines 43 through 45 we see a value, reference, and and r-value
reference being passed to a tt(std::thread): with 
the functions running the threads expecting matching argument types.
    
    it() Line 47 fails to compile, as a value argument doesn't match the
reference expected by tt(refArg). Note that this problem was solved in line 43
by using the tt(std::ref) function.

    it() On the other hand lines 49 and 58 compile OK, as tt(int) values and
class-types supporting move operations can be passed as values to functions
expecting r-value references. In this case notice that the functions expecting
the r-value references do not access the provided arguments (except for the
actions performed by their move constructors), but use move construction to
create temporary values or objects on which the functions operate.

    it() Lines 52 and 55 won't compile as the tt(NoMove) struct doesn't offer
a move constructor.

    it() Member functions of classes can also be used as thread functions. In
those cases the constructor's first argument must be the address of the member
function, the second argument must be a pointer (or reference, or object) for
which the member function is called as thread function, while subsequent
arguments are passed as arguments to the member function. Here is a simple
example illustrating these options:
    verbinsert(//main examples/memberthreads.cc)
    )

    Be careful when passing local variables as arguments to thread objects: if
the thread continues to run when the function whose local variables are used
terminates, then the thread suddenly uses wild pointers or wild references, as
the local variables no longer exist. To prevent this from happening
(illustrated by the next example) do as follows:
        itemization(
        it() pass an anonymous copy of the local variable as argument to the
tt(thread) constructor, or

        it() call tt(join) on the thread object to ensure that the thread has
finished within the local variable's lifetime.
        )

    verbinclude(-ans4 examples/locals.cc)
    In line 18 be sure not to call tt(std::ref(text)) instead of
tt(std::string{ text }).

    If the thread cannot be created a tt(std::system_error) exception is
thrown.

Since this constructor not only accepts functions but also function objects as
its first argument, a emi(local context) may be passed to the function
object's constructor. Here is an example of a thread receiving a function
object using a local context:
        verbinclude(-a examples/functorthread.cc)
        )
    )
    The class tt(std::thread) does not provide a copy constructor.

The following members are available:
    itemization(
    itt(thread &operator=(thread &&tmp) noexcept):
       quote(If the operator's left-hand side operand (lhs) is a joinable
thread, then tt(terminate) is called. Otherwise, tt(tmp) is assigned to the
operator's lhs and tt(tmp's) state is changed to the thread's default state
(i.e., tt(thread())).)

    ithtq(detach)(void detach())
       (Requires tt(joinable) (see below) to return tt(true).  The thread for
which tt(detach) is called continues to run. The (e.g., parent) thread calling
tt(detach) continues immediately beyond the tt(detach)-call.  After calling
tt(object.detach()), `tt(object)' no longer represents the (possibly still
continuing but now detached) thread of execution. It is the detached thread's
implementation's responsibility to release its resources when its execution
ends.

Since tt(detach) disconnects a thread from the running program, e.g.,
tt(main) no longer can wait for the thread's completion.  As a program
ends when tt(main) ends, its still running detached threads also stop, and
a program may not properly finish all its threads, as demonstrated by
the following example: 
            verbinclude(-a examples/threads2.cc)

    A detached thread may very well continue to run after the function that
launched it has finished. Here, too, you should be very careful not to pass
local variables to the detached thread, as their references or pointers will
be undefined once the function defining the local variables terminates:
            verbinclude(-a examples/detached.cc)
        )

    ithtq(get_id)(id get_id() const noexcept)
       (If the current object does not represent a running thread 
hi(id)tt(thread::id()) is returned. Otherwise, the thread's unique ID
(also obtainable from within the thread via tt(this_thread::get_id())) is
returned.)

    ithtq(hardware_concurrency)
        (unsigned thread::hardware_concurrency() noexecpt)
        (This static member returns the number of threads that can run at the
same time on the current computer. On a stand-alone multi-core computer it
(probably) returns the number of cores.)

    ithtq(join)(void join())
       (Requires tt(joinable) to return tt(true).  If the thread for which
tt(join) is called hasn't finished yet then the thread calling tt(join) will
be suspended (also called em(blocked)) until the thread for which tt(join) is
called has completed. Following its completion the object whose tt(join)
member was called no longer represents a running thread, and its tt(get_id)
member will return tt(std::thread::id()).

        This member was used in several examples shown so far. As noted: when
tt(main) ends while a joinable thread is still running, tt(terminate) is
called, aborting the program.)

    ithtq(joinable)(bool joinable() const noexcept)
       (returns tt(object.get_id() != id()), where tt(object) is the
tt(thread) object for which tt(joinable) was called.)

    ithtq(native_handle)(native_handle_type  native_handle())
       (returns the thread's em(handle) (implementation defined). This handle
can be passed to functions like ti(pthread_getschedparam) and
ti(pthread_setschedparam) to get/set the thread's scheduling policy and
parameters.)

    ithtq(swap)(void swap(thread &other) noexcept)
       (The states of the tt(thread) object for which tt(swap) was called and
tt(other) are swapped. Note that threads may always be swapped, even when
their thread functions are currently being executed.)
    )

    Things to note:
    itemization(
    it() When intending to define an anonymous thread it may appear not to
start, unless you immediately also call tt(join). E.g.,
            verb(void doSomething();
int main()
{
    thread(doSomething);        // nothing happens??
    thread(doSomething).join(); // doSomething is executed??
})

This similar to the situation we encountered in section ref(UNIFORMINIT):
the first statement doesn't define an anonymous tt(thread) object at all. It
simply defines the tt(thread) object tt(doSomething). Consequently,
compilation of the second statement fails, as there is no tt(thread(thread &))
constructor. When the first statement is omitted, the tt(doSomething) function
is executed by the second statement. If the second statement is omitted, a
default constructed tt(thread) object by the name of tt(doSomething) is
defined.

    it() A thread only starts after its construction has completed. This
includes move constructions or move assignments. E.g., in a statement like
        verb(    thread object(thread(doSomething));)

the move constructor is used to transfer control from an anonymous thread
executing tt(doSomething) to the thread tt(object). Only after tt(object)'s
construction has completed tt(doSomething) is started in the separate thread.
    
    it() Exceptions thrown from the thread (e.g., by the function defining the
thread's actions) are local to the executed thread. Either they must be caught
by the executing thread (as each running thread has its own execution stack),
or they can be passed to the starting thread using a tt(packaged_task) and a
tt(future) (cf., respectively, sections ref(PACKAGE) and ref(FUTURE)).
    )

    A thread ends when the function executing a thread finishes. When a
tt(thread) object is destroyed while its thread function is still running,
tt(terminate) is called, aborting the program's end. Bad news: the destructors
of existing objects aren't called and exceptions that are thrown are left
uncaught. This happens in the following program as the thread is still active
when tt(main) ends:
        verbinclude(-a examples/terminate.cc)
    There are several ways to solve this problem. One of them is discussed in
the next section.
