Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
pistache
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
pistache
Commits
955ae9ac
Commit
955ae9ac
authored
Nov 12, 2015
by
octal
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Promise::then now returns a new Promise so that chaining now becomes easier
parent
5455a471
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
104 additions
and
60 deletions
+104
-60
src/async.h
src/async.h
+102
-55
tests/async_test.cc
tests/async_test.cc
+2
-5
No files found.
src/async.h
View file @
955ae9ac
...
...
@@ -67,10 +67,10 @@ namespace Async {
class
Core
;
class
Request
{
public:
virtual
void
resolve
(
const
std
::
shared_ptr
<
Private
::
Core
>&
core
)
=
0
;
virtual
void
reject
(
const
std
::
shared_ptr
<
Private
::
Core
>&
core
)
=
0
;
virtual
void
disconnect
()
=
0
;
};
struct
Core
{
...
...
@@ -83,10 +83,37 @@ namespace Async {
std
::
vector
<
std
::
shared_ptr
<
Request
>>
requests
;
virtual
void
*
memory
()
=
0
;
template
<
typename
T
,
typename
...
Args
>
void
construct
(
Args
&&
...
args
)
{
void
*
mem
=
memory
();
new
(
mem
)
T
(
std
::
forward
<
Args
>
(
args
)...);
state
=
State
::
Fulfilled
;
}
};
}
namespace
detail
{
template
<
typename
T
>
struct
RemovePromise
{
typedef
T
Type
;
};
template
<
typename
T
>
struct
RemovePromise
<
Promise
<
T
>>
{
typedef
T
Type
;
};
template
<
typename
Func
>
struct
result_of
:
public
result_of
<
decltype
(
&
Func
::
operator
())
>
{
};
template
<
typename
R
,
typename
Class
,
typename
...
Args
>
struct
result_of
<
R
(
Class
::*
)
(
Args
...)
const
>
{
typedef
R
Type
;
};
}
class
Resolver
{
public:
Resolver
(
const
std
::
shared_ptr
<
Private
::
Core
>
&
core
)
...
...
@@ -100,9 +127,7 @@ namespace Async {
if
(
core_
->
state
!=
State
::
Pending
)
throw
Error
(
"Attempt to resolve a fulfilled promise"
);
void
*
mem
=
core_
->
memory
();
new
(
mem
)
Type
(
std
::
forward
<
Arg
>
(
arg
));
core_
->
state
=
State
::
Fulfilled
;
core_
->
construct
<
Type
>
(
std
::
forward
<
Arg
>
(
arg
));
for
(
const
auto
&
req
:
core_
->
requests
)
{
req
->
resolve
(
core_
);
}
...
...
@@ -158,15 +183,9 @@ namespace Async {
class
Promise
:
public
PromiseBase
{
public:
typedef
std
::
function
<
void
(
Resolver
&
,
Rejection
&
)
>
ResolveFunc
;
struct
Request
:
public
Private
::
Request
{
virtual
Promise
<
T
>
chain
()
=
0
;
void
disconnect
()
{
}
template
<
typename
U
>
friend
class
Promise
;
}
;
typedef
std
::
function
<
void
(
Resolver
&
,
Rejection
&
)
>
ResolveFunc
;
Promise
(
ResolveFunc
func
)
:
core_
(
std
::
make_shared
<
CoreT
>
())
...
...
@@ -191,17 +210,32 @@ namespace Async {
bool
isRejected
()
const
{
return
core_
->
state
==
State
::
Rejected
;
}
template
<
typename
ResolveFunc
,
typename
RejectFunc
>
std
::
shared_ptr
<
Request
>
then
(
ResolveFunc
&&
resolveFunc
,
RejectFunc
&&
rejectFunc
,
Continuation
type
=
Continuation
::
Direct
)
{
auto
then
(
ResolveFunc
&&
resolveFunc
,
RejectFunc
&&
rejectFunc
,
Continuation
type
=
Continuation
::
Direct
)
->
Promise
<
typename
detail
::
RemovePromise
<
typename
detail
::
result_of
<
ResolveFunc
>::
Type
>::
Type
>
{
static_assert
(
detail
::
IsCallable
<
ResolveFunc
,
T
>::
value
,
"Function is not compatible with underlying promise type"
);
typedef
typename
detail
::
RemovePromise
<
typename
detail
::
result_of
<
ResolveFunc
>::
Type
>::
Type
RetType
;
Promise
<
RetType
>
promise
;
// Due to how template argument deduction works on universal references, we need to remove any reference from
// the deduced function type, fun fun fun
typedef
typename
std
::
remove_reference
<
ResolveFunc
>::
type
ResolveFuncType
;
typedef
typename
std
::
remove_reference
<
RejectFunc
>::
type
RejectFuncType
;
std
::
shared_ptr
<
Request
>
req
;
std
::
shared_ptr
<
Private
::
Request
>
req
;
req
.
reset
(
ContinuationFactory
<
ResolveFuncType
>::
create
(
std
::
forward
<
ResolveFunc
>
(
resolveFunc
),
std
::
forward
<
RejectFunc
>
(
rejectFunc
)));
promise
.
core_
,
std
::
forward
<
ResolveFunc
>
(
resolveFunc
),
std
::
forward
<
RejectFunc
>
(
rejectFunc
)));
if
(
isFulfilled
())
{
req
->
resolve
(
core_
);
...
...
@@ -210,8 +244,9 @@ namespace Async {
req
->
reject
(
core_
);
}
core_
->
requests
.
push_back
(
req
);
return
req
;
core_
->
requests
.
push_back
(
req
);
return
promise
;
}
private:
...
...
@@ -243,15 +278,14 @@ namespace Async {
typedef
Core
<
T
>
CoreT
;
Promise
(
const
std
::
shared_ptr
<
CoreT
>&
core
)
:
core_
(
core
)
,
resolver_
(
core
)
,
rejection_
(
core
)
Promise
(
)
:
core_
(
std
::
make_shared
<
Core
<
T
>>
()
)
,
resolver_
(
core
_
)
,
rejection_
(
core
_
)
{
}
struct
Continuable
:
public
Request
{
struct
Continuable
:
public
Private
::
Request
{
Continuable
()
:
resolveCount_
(
0
)
,
rejectCount_
(
0
)
...
...
@@ -286,7 +320,8 @@ namespace Async {
template
<
typename
ResolveFunc
,
typename
RejectFunc
>
struct
ThenContinuation
:
public
Continuable
{
ThenContinuation
(
ResolveFunc
&&
resolveFunc
,
RejectFunc
&&
rejectFunc
)
ThenContinuation
(
ResolveFunc
&&
resolveFunc
,
RejectFunc
&&
rejectFunc
)
:
resolveFunc_
(
std
::
forward
<
ResolveFunc
>
(
resolveFunc
))
,
rejectFunc_
(
std
::
forward
<
RejectFunc
>
(
rejectFunc
))
{
...
...
@@ -300,53 +335,43 @@ namespace Async {
rejectFunc_
(
core
->
exc
);
}
Promise
<
T
>
chain
()
{
throw
Error
(
"The request is not chainable"
);
}
std
::
shared_ptr
<
Private
::
Core
>
chain_
;
ResolveFunc
resolveFunc_
;
RejectFunc
rejectFunc_
;
};
template
<
typename
ResolveFunc
,
typename
RejectFunc
,
typename
Return
>
struct
ThenReturnContinuation
:
public
Continuable
{
ThenReturnContinuation
(
ResolveFunc
&&
resolveFunc
,
RejectFunc
&&
rejectFunc
)
:
resolveFunc_
(
std
::
forward
<
ResolveFunc
>
(
resolveFunc
))
ThenReturnContinuation
(
const
std
::
shared_ptr
<
Private
::
Core
>&
chain
,
ResolveFunc
&&
resolveFunc
,
RejectFunc
&&
rejectFunc
)
:
chain_
(
chain
)
,
resolveFunc_
(
std
::
forward
<
ResolveFunc
>
(
resolveFunc
))
,
rejectFunc_
(
std
::
forward
<
RejectFunc
>
(
rejectFunc
))
{
}
void
doResolve
(
const
std
::
shared_ptr
<
CoreT
>&
core
)
const
{
auto
ret
=
resolveFunc_
(
core
->
value
());
result
=
Some
(
std
::
move
(
ret
));
chain_
->
construct
<
decltype
(
ret
)
>
(
std
::
move
(
ret
));
}
void
doReject
(
const
std
::
shared_ptr
<
CoreT
>&
core
)
const
{
rejectFunc_
(
core
->
exc
);
}
Promise
<
Return
>
chain
()
{
typedef
typename
CoreT
::
template
Rebind
<
Return
>
::
Type
CoreType
;
auto
core
=
std
::
make_shared
<
CoreType
>
();
optionally_do
(
result
,
[
&
core
](
Return
&&
result
)
{
void
*
mem
=
core
->
memory
();
new
(
mem
)
Return
(
std
::
move
(
result
));
core
->
state
=
State
::
Fulfilled
;
});
return
Promise
<
Return
>
(
core
);
}
std
::
shared_ptr
<
Private
::
Core
>
chain_
;
ResolveFunc
resolveFunc_
;
RejectFunc
rejectFunc_
;
mutable
Optional
<
Return
>
result
;
};
template
<
typename
ResolveFunc
,
typename
RejectFunc
>
struct
ThenChainContinuation
:
public
Continuable
{
ThenChainContinuation
(
ResolveFunc
&&
resolveFunc
,
RejectFunc
&&
rejectFunc
)
:
resolveFunc_
(
std
::
forward
<
ResolveFunc
>
(
resolveFunc
))
ThenChainContinuation
(
const
std
::
shared_ptr
<
Private
::
Core
>&
chain
,
ResolveFunc
&&
resolveFunc
,
RejectFunc
&&
rejectFunc
)
:
chain_
(
chain
)
,
resolveFunc_
(
std
::
forward
<
ResolveFunc
>
(
resolveFunc
))
,
rejectFunc_
(
std
::
forward
<
RejectFunc
>
(
rejectFunc
))
{
}
...
...
@@ -359,11 +384,7 @@ namespace Async {
rejectFunc_
(
core
->
exc
);
}
Promise
<
T
>
chain
()
{
auto
core
=
std
::
make_shared
<
CoreT
>
();
return
Promise
<
T
>
(
core
);
}
std
::
shared_ptr
<
Private
::
Core
>
chain_
;
ResolveFunc
resolveFunc_
;
RejectFunc
rejectFunc_
;
...
...
@@ -375,8 +396,11 @@ namespace Async {
template
<
typename
R
,
typename
Class
,
typename
...
Args
>
struct
ContinuationFactory
<
R
(
Class
::*
)(
Args
...)
const
>
{
template
<
typename
ResolveFunc
,
typename
RejectFunc
>
static
Continuable
*
create
(
ResolveFunc
&&
resolveFunc
,
RejectFunc
&&
rejectFunc
)
{
static
Continuable
*
create
(
const
std
::
shared_ptr
<
Private
::
Core
>&
chain
,
ResolveFunc
&&
resolveFunc
,
RejectFunc
&&
rejectFunc
)
{
return
new
ThenReturnContinuation
<
ResolveFunc
,
RejectFunc
,
R
>
(
chain
,
std
::
forward
<
ResolveFunc
>
(
resolveFunc
),
std
::
forward
<
RejectFunc
>
(
rejectFunc
));
}
...
...
@@ -385,7 +409,9 @@ namespace Async {
template
<
typename
Class
,
typename
...
Args
>
struct
ContinuationFactory
<
void
(
Class
::*
)(
Args
...)
const
>
{
template
<
typename
ResolveFunc
,
typename
RejectFunc
>
static
Continuable
*
create
(
ResolveFunc
&&
resolveFunc
,
RejectFunc
&&
rejectFunc
)
{
static
Continuable
*
create
(
const
std
::
shared_ptr
<
Private
::
Core
>&
chain
,
ResolveFunc
&&
resolveFunc
,
RejectFunc
&&
rejectFunc
)
{
return
new
ThenContinuation
<
ResolveFunc
,
RejectFunc
>
(
std
::
forward
<
ResolveFunc
>
(
resolveFunc
),
std
::
forward
<
RejectFunc
>
(
rejectFunc
));
...
...
@@ -395,8 +421,11 @@ namespace Async {
template
<
typename
U
,
typename
Class
,
typename
...
Args
>
struct
ContinuationFactory
<
Promise
<
U
>
(
Class
::*
)(
Args
...)
const
>
{
template
<
typename
ResolveFunc
,
typename
RejectFunc
>
static
Continuable
*
create
(
ResolveFunc
&&
resolveFunc
,
RejectFunc
&&
rejectFunc
)
{
static
Continuable
*
create
(
const
std
::
shared_ptr
<
Private
::
Core
>&
chain
,
ResolveFunc
&&
resolveFunc
,
RejectFunc
&&
rejectFunc
)
{
return
new
ThenChainContinuation
<
ResolveFunc
,
RejectFunc
>
(
chain
,
std
::
forward
<
ResolveFunc
>
(
resolveFunc
),
std
::
forward
<
RejectFunc
>
(
rejectFunc
));
}
...
...
@@ -407,4 +436,22 @@ namespace Async {
Rejection
rejection_
;
};
template
<
>
class
Promise
<
void
>
{
public:
Promise
()
:
core_
(
std
::
make_shared
<
Core
>
())
{
}
public:
struct
Core
:
public
Private
::
Core
{
Core
()
:
Private
::
Core
(
State
::
Pending
)
{
}
void
*
memory
()
{
return
nullptr
;
}
};
std
::
shared_ptr
<
Core
>
core_
;
};
}
// namespace Async
tests/async_test.cc
View file @
955ae9ac
...
...
@@ -30,6 +30,7 @@ TEST(async_test, basic_test) {
p1
.
then
([
&
](
int
v
)
{
val
=
v
;
},
Async
::
NoExcept
);
ASSERT_EQ
(
val
,
10
);
{
Async
::
Promise
<
int
>
p2
=
doAsync
(
10
);
p2
.
then
([](
int
result
)
{
ASSERT_EQ
(
result
,
20
);
},
...
...
@@ -58,7 +59,6 @@ TEST(async_test, chain_test) {
p1
.
then
([](
int
result
)
{
return
result
*
2
;
},
Async
::
NoExcept
)
->
chain
()
.
then
([](
int
result
)
{
std
::
cout
<<
"Result = "
<<
result
<<
std
::
endl
;
},
Async
::
NoExcept
);
...
...
@@ -67,13 +67,10 @@ TEST(async_test, chain_test) {
resolve
(
10
);
});
#if 0
p2
.then([](int result) { return result * 2.0; }, Async::IgnoreException)
->chain()
.
then
([](
int
result
)
{
return
result
*
2.2901
;
},
Async
::
IgnoreException
)
.
then
([](
double
result
)
{
std
::
cout
<<
"Result = "
<<
result
<<
std
::
endl
;
},
Async
::
IgnoreException
);
#endif
}
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