1.. _Advanced_Topic_Other_Kinds_of_Iteration_Spaces:
2
3Advanced Topic: Other Kinds of Iteration Spaces
4===============================================
5
6
7The examples so far have used the class ``blocked_range<T>`` to specify ranges.
8This class is useful in many situations, but it does not fit every situation.
9You can use |full_name| to define your own iteration space objects. The object
10must specify how it can be split into subspaces by providing a basic splitting
11constructor, an optional proportional splitting constructor, and two predicate
12methods. If your class is called ``R``, the methods and constructors should be
13as follows:
14
15
16::
17
18
19   class R {
20       // True if range is empty
21       bool empty() const;
22       // True if range can be split into non-empty subranges
23       bool is_divisible() const;
24       // Splits r into subranges r and *this
25       R( R& r, split );
26       // (optional) Splits r into subranges r and *this in proportion p
27       R( R& r, proportional_split p );
28       ...
29   };
30
31
32
33
34The method ``empty`` should return true if the range is empty. The
35method ``is_divisible`` should return true if the range can be split
36into two non-empty subspaces, and such a split is worth the overhead.
37The basic splitting constructor should take two arguments:
38
39
40-  The first of type ``R``
41
42
43-  The second of type oneapi::tbb::split
44
45
46The second argument is not used; it serves only to distinguish the
47constructor from an ordinary copy constructor. The basic splitting
48constructor should attempt to split ``r`` roughly into two halves, and
49update ``r`` to be the first half, and set the constructed object as the
50second half.
51
52
53Unlike the basic splitting constructor, the proportional splitting
54constructor is optional and takes the second argument of type
55``oneapi::tbb::proportional_split``. The type has methods ``left`` and ``right``
56that return the values of the proportion. These values should be used to
57split ``r`` accordingly, so that the updated ``r`` corresponds to the
58left part of the proportion, and the constructed object corresponds to
59the right part.
60
61
62Both splitting constructors should guarantee that the updated ``r`` part
63and the constructed object are not empty. The parallel algorithm
64templates call the splitting constructors on ``r`` only if
65``r.is_divisible`` is true.
66
67
68The iteration space does not have to be linear. Look at
69``oneapi/tbb/blocked_range2d.h`` for an example of a range that is
70two-dimensional. Its splitting constructor attempts to split the range
71along its longest axis. When used with ``parallel_for``, it causes the
72loop to be "recursively blocked" in a way that improves cache usage.
73This nice cache behavior means that using ``parallel_for`` over a
74``blocked_range2d<T>`` can make a loop run faster than the sequential
75equivalent, even on a single processor.
76