Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
las3_pub
/
predictable_parallel_patterns
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
d3b64a85
authored
Nov 06, 2019
by
FritzFlorian
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
WIP: Initialization of continuation chains.
parent
740ae661
Pipeline
#1333
failed with stages
in 25 seconds
Changes
3
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
73 additions
and
10 deletions
+73
-10
lib/pls/include/pls/internal/data_structures/delayed_initialization_wrapper.h
+9
-1
lib/pls/include/pls/internal/scheduling/cont_manager.h
+38
-5
lib/pls/include/pls/internal/scheduling/continuation.h
+26
-4
No files found.
lib/pls/include/pls/internal/data_structures/delayed_initialization_wrapper.h
View file @
d3b64a85
...
...
@@ -35,11 +35,19 @@ class delayed_initialization_wrapper {
template
<
typename
...
ARGS
>
void
initialize
(
ARGS
&&
...
args
)
{
PLS_ASSERT
(
initialized_
,
"Can only initialize delayed wrapper object once!"
)
PLS_ASSERT
(
!
initialized_
,
"Can only initialize delayed wrapper object once!"
)
new
(
memory_
)
T
(
std
::
forward
<
ARGS
>
(
args
)...);
initialized_
=
true
;
}
void
destroy
()
{
PLS_ASSERT
(
initialized_
,
"Can only destroy initialized objects!"
)
memory_
->~
T
();
initialized_
=
false
;
}
T
&
object
()
{
PLS_ASSERT
(
initialized_
,
"Can not use an uninitialized delayed wrapper object!"
)
return
*
reinterpret_cast
<
T
*>
(
memory_
);
...
...
lib/pls/include/pls/internal/scheduling/cont_manager.h
View file @
d3b64a85
...
...
@@ -3,6 +3,8 @@
#define PLS_CONT_MANAGER_H_
#include <memory>
#include <tuple>
#include <array>
#include "pls/internal/data_structures/aligned_stack.h"
#include "pls/internal/scheduling/continuation.h"
...
...
@@ -13,14 +15,45 @@ namespace scheduling {
class
cont_manager
{
public
:
explicit
cont_manager
(
size_t
num_conts
,
size_t
max_cont_size
,
data_structures
::
aligned_stack
&
cont_storage
)
:
num_conts_
{
num_conts
},
max_cont_size_
{
max_cont_size
},
cont_storage_
{
cont_storage
}
{
//TODO: Init linked list like structure
template
<
size_t
NUM_CONTS
,
size_t
MAX_CONT_SIZE
>
explicit
cont_manager
(
data_structures
::
aligned_stack
&
cont_storage
)
{
// First node is currently active and our local start
start_node_
=
active_node_
=
init_cont_node
<
MAX_CONT_SIZE
>
(
cont_storage
,
nullptr
,
nullptr
);
// Build up chain after it
continuation_node
*
current_node
=
start_node_
;
for
(
size_t
i
=
1
;
i
<
NUM_CONTS
;
i
++
)
{
continuation_node
*
next_node
=
init_cont_node
<
MAX_CONT_SIZE
>
(
cont_storage
,
start_node_
,
current_node
);
current_node
->
set_prev
(
next_node
);
}
};
continuation_node
*
fast_path_get_next
()
{
active_node_
=
active_node_
->
get_next
();
return
active_node_
;
}
void
fast_path_return
()
{
active_node_
=
active_node_
->
get_prev
();
}
private
:
template
<
size_t
MAX_CONT_SIZE
>
static
continuation_node
*
init_cont_node
(
data_structures
::
aligned_stack
&
cont_storage
,
continuation_node
*
cont_chain_start
,
continuation_node
*
prev
)
{
// Represents one cont node and its corresponding memory buffer (as one continuous block of memory).
using
cont_node_memory_pair
=
std
::
tuple
<
continuation_node
,
std
::
array
<
char
,
MAX_CONT_SIZE
-
sizeof
(
continuation_node
)
>>
;
char
*
tuple_memory
=
cont_storage
.
push_bytes
<
cont_node_memory_pair
>
();
char
*
cont_node_address
=
tuple_memory
;
char
*
cont_node_memory_address
=
tuple_memory
+
sizeof
(
continuation_node
);
return
new
(
cont_node_address
)
continuation_node
(
cont_node_memory_address
,
cont_chain_start
,
prev
);
}
private
:
con
st
size_t
num_conts_
,
max_cont_siz
e_
;
data_structures
::
aligned_stack
&
cont_storag
e_
;
con
tinuation_node
*
start_nod
e_
;
continuation_node
*
active_nod
e_
;
};
template
<
size_t
NUM_CONTS
,
size_t
MAX_CONT_SIZE
>
...
...
lib/pls/include/pls/internal/scheduling/continuation.h
View file @
d3b64a85
...
...
@@ -20,10 +20,27 @@ class base_continuation {
class
continuation_node
{
public
:
continuation_node
(
char
*
continuation_memory
,
continuation_node
*
cont_chain_start
,
continuation_node
*
prev
)
:
continuation_memory_
{
continuation_memory
},
continuation_
{
nullptr
},
cont_chain_start_
{
cont_chain_start
},
prev_
{
prev
},
next_
{
nullptr
},
offered_chain_
{
nullptr
}
{}
void
set_cont_chain_start
(
continuation_node
*
cont_chain_start
)
{
cont_chain_start_
=
cont_chain_start
;
}
continuation_node
*
get_cont_chain_start
()
{
return
cont_chain_start_
;
}
void
set_next
(
continuation_node
*
next
)
{
next_
=
next
;
}
continuation_node
*
get_next
()
{
return
next_
;
}
void
set_prev
(
continuation_node
*
prev
)
{
prev_
=
prev
;
}
continuation_node
*
get_prev
()
{
return
prev_
;
}
base_continuation
*
continuation
()
{
return
continuation_
;
}
private
:
// Pointer to memory region reserved for the companion continuation.
// Must be a buffer big enough to hold any continuation encountered in the program.
char
*
continuation_memory_
;
base_continuation
*
continuation_
;
// Linked list property of continuations (continuation chains as memory management).
...
...
@@ -47,6 +64,10 @@ class continuation : public base_continuation {
// E.g. handle passing the result to the parent continuation
function_
.
object
()(
result_1_
.
object
(),
result_2_
.
object
());
}
// Warning: De-constructor only called once the continuation is actually needed.
// This should be a non issue, as all memory in the continuation is uninitialized
// until the first use anyways to save runtime.
~
continuation
()
override
=
default
;
template
<
typename
R1ARG
>
...
...
@@ -76,14 +97,15 @@ class continuation : public base_continuation {
template
<
typename
T
>
using
delayed_init
=
data_structures
::
delayed_initialization_wrapper
<
T
>
;
delayed_init
<
R1
>
result_1_
;
delayed_init
<
R2
>
result_2_
;
delayed_init
<
F
>
function_
;
// Also uninitialized at first, only take the atomic write on the slow path.
// The stealer will init it to 2 while stealing, the 'stolen' sync will then make sure
// everyone sees the value in correct order.
std
::
atomic
<
unsigned
short
>
results_missing_
{};
// All fields/actual values stay uninitialized (save time on the fast path if we don not need them).
delayed_init
<
R1
>
result_1_
;
delayed_init
<
R2
>
result_2_
;
delayed_init
<
F
>
function_
;
};
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment