@@ -187,6 +187,25 @@ struct _State_deleter : _Deleter_base<_Ty> { // manage allocator and deletion st
187
187
_Alloc _My_alloc;
188
188
};
189
189
190
+ template <class _Ty>
191
+ struct __declspec(novtable) _Clonable_deleter_base : _Deleter_base<_Ty> {
192
+ // TRANSITION, ABI, should be fused into _Deleter_base
193
+ virtual _Associated_state<_Ty>* _Move_clone(_Associated_state<_Ty>&&) = 0;
194
+ };
195
+
196
+ template <class _Ty, class _Derived, class _Alloc>
197
+ struct _State_deleter_v2 : _Clonable_deleter_base<_Ty> { // manage allocator and deletion state objects
198
+ _State_deleter_v2(const _Alloc& _Al) : _My_alloc(_Al) {}
199
+
200
+ _State_deleter_v2(const _State_deleter_v2&) = delete;
201
+ _State_deleter_v2& operator=(const _State_deleter_v2&) = delete;
202
+
203
+ void _Delete(_Associated_state<_Ty>* _State) noexcept override;
204
+ _Associated_state<_Ty>* _Move_clone(_Associated_state<_Ty>&& _Src) override;
205
+
206
+ _Alloc _My_alloc;
207
+ };
208
+
190
209
template <class _Ty>
191
210
union _Result_holder {
192
211
_Result_holder() noexcept {}
@@ -389,6 +408,10 @@ public:
389
408
}
390
409
}
391
410
411
+ _Mydel* _Get_deleter() const noexcept { // get deleter for cloning
412
+ return _Deleter;
413
+ }
414
+
392
415
protected:
393
416
void _Maybe_run_deferred_function(unique_lock<mutex>& _Lock) { // run a deferred function if not already done
394
417
if (!_Running) { // run the function
@@ -495,19 +518,13 @@ public:
495
518
template <class _Fty2, enable_if_t<!is_same_v<_Remove_cvref_t<_Fty2>, _Function_type>, int> = 0>
496
519
explicit _Packaged_state(_Fty2&& _Fnarg) : _Fn(_Secret_copyability_ignoring_tag{}, _STD forward<_Fty2>(_Fnarg)) {}
497
520
498
- #if _HAS_FUNCTION_ALLOCATOR_SUPPORT
499
- template <class _Alloc>
500
- _Packaged_state(const _Function_type& _Fnarg, const _Alloc& _Al, _Mydel* _Dp)
501
- : _Mybase(_Dp), _Fn(allocator_arg, _Al, _Fnarg) {}
502
-
503
521
template <class _Alloc>
504
522
_Packaged_state(_Function_type&& _Fnarg, const _Alloc& _Al, _Mydel* _Dp)
505
- : _Mybase(_Dp), _Fn(allocator_arg, _Al, _STD move(_Fnarg)) {}
523
+ : _Mybase(_Dp), _Fn(_Secret_copyability_ignoring_tag{}, allocator_arg, _Al, _STD move(_Fnarg)) {}
506
524
507
525
template <class _Fty2, class _Alloc, enable_if_t<!is_same_v<_Remove_cvref_t<_Fty2>, _Function_type>, int> = 0>
508
526
_Packaged_state(_Fty2&& _Fnarg, const _Alloc& _Al, _Mydel* _Dp)
509
527
: _Mybase(_Dp), _Fn(_Secret_copyability_ignoring_tag{}, allocator_arg, _Al, _STD forward<_Fty2>(_Fnarg)) {}
510
- #endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT
511
528
512
529
void _Call_deferred(_ArgTypes... _Args) { // set deferred call
513
530
_TRY_BEGIN
@@ -543,10 +560,7 @@ public:
543
560
_CATCH_END
544
561
}
545
562
546
- const auto& _Get_fn() const& {
547
- return _Fn;
548
- }
549
- auto&& _Get_fn() && noexcept {
563
+ _Function_type&& _Get_fn() && noexcept {
550
564
return _STD move(_Fn);
551
565
}
552
566
@@ -569,11 +583,14 @@ _Associated_state<_Ty>* _Make_associated_state(const _Alloc& _Al) {
569
583
return _STD _Unfancy(_Res.release()); // ownership transferred to caller
570
584
}
571
585
572
- #if _HAS_FUNCTION_ALLOCATOR_SUPPORT
573
586
template <class _Pack_state, class _Fty2, class _Alloc>
574
587
_Pack_state* _Make_packaged_state(_Fty2&& _Fnarg, const _Alloc& _Al) {
575
588
// construct a _Packaged_state object with an allocator from an rvalue function object
576
- using _Delty = _State_deleter<typename _Pack_state::_Mybase::_State_type, _Pack_state, _Alloc>;
589
+ #ifdef _CPPRTTI // TRANSITON, ABI, should not rely on RTTI
590
+ using _Delty = _State_deleter_v2<typename _Pack_state::_Mybase::_State_type, _Pack_state, _Alloc>;
591
+ #else // ^^^ defined(_CPPRTTI) / !defined(_CPPRTTI) vvv
592
+ using _Delty = _State_deleter<typename _Pack_state::_Mybase::_State_type, _Pack_state, _Alloc>;
593
+ #endif // ^^^ !defined(_CPPRTTI) ^^^
577
594
using _Aldelty = _Rebind_alloc_t<_Alloc, _Delty>;
578
595
using _Alstate = _Rebind_alloc_t<_Alloc, _Pack_state>;
579
596
@@ -584,7 +601,26 @@ _Pack_state* _Make_packaged_state(_Fty2&& _Fnarg, const _Alloc& _Al) {
584
601
(void) _Del.release(); // ownership of _Del.get() now transferred to _Res
585
602
return _STD _Unfancy(_Res.release()); // ownership transferred to caller
586
603
}
587
- #endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT
604
+
605
+ template <class _Ty, class _Derived, class _Alloc>
606
+ void _State_deleter_v2<_Ty, _Derived, _Alloc>::_Delete(_Associated_state<_Ty>* _State) noexcept {
607
+ // delete _State and this using stored allocator
608
+ using _State_allocator = _Rebind_alloc_t<_Alloc, _Derived>;
609
+ _State_allocator _St_alloc(_My_alloc);
610
+
611
+ using _Deleter_allocator = _Rebind_alloc_t<_Alloc, _State_deleter_v2>;
612
+ _Deleter_allocator _Del_alloc(_My_alloc);
613
+
614
+ _Derived* _Ptr = static_cast<_Derived*>(_State);
615
+
616
+ _STD _Delete_plain_internal(_St_alloc, _Ptr);
617
+ _STD _Delete_plain_internal(_Del_alloc, this);
618
+ }
619
+
620
+ template <class _Ty, class _Derived, class _Alloc>
621
+ _Associated_state<_Ty>* _State_deleter_v2<_Ty, _Derived, _Alloc>::_Move_clone(_Associated_state<_Ty>&& _Src) {
622
+ return _STD _Make_packaged_state<_Derived>(static_cast<_Derived&&>(_Src)._Get_fn(), _My_alloc);
623
+ }
588
624
589
625
template <class _Rx>
590
626
class _Deferred_async_state : public _Packaged_state<_Rx()> {
@@ -1185,9 +1221,6 @@ private:
1185
1221
_Promise<int> _MyPromise;
1186
1222
};
1187
1223
1188
- template <class _Ty, class _Alloc>
1189
- struct uses_allocator<promise<_Ty>, _Alloc> : true_type {};
1190
-
1191
1224
_EXPORT_STD template <class _Ty>
1192
1225
void swap(promise<_Ty>& _Left, promise<_Ty>& _Right) noexcept {
1193
1226
_Left.swap(_Right);
@@ -1211,21 +1244,19 @@ public:
1211
1244
template <class _Fty2, enable_if_t<!is_same_v<_Remove_cvref_t<_Fty2>, packaged_task>, int> = 0>
1212
1245
explicit packaged_task(_Fty2&& _Fnarg) : _MyPromise(new _MyStateType(_STD forward<_Fty2>(_Fnarg))) {
1213
1246
static_assert(_Is_invocable_r<_Ret, decay_t<_Fty2>&, _ArgTypes...>::value,
1214
- "The function object must be callable with _ArgTypes... and return _Ret (N4988 [futures.task.members]/3).");
1247
+ "The function object must be callable with _ArgTypes... and return _Ret (N5008 [futures.task.members]/3).");
1215
1248
}
1216
1249
1217
1250
packaged_task(packaged_task&&) noexcept = default;
1218
1251
1219
1252
packaged_task& operator=(packaged_task&&) noexcept = default;
1220
1253
1221
- #if _HAS_FUNCTION_ALLOCATOR_SUPPORT
1222
1254
template <class _Fty2, class _Alloc, enable_if_t<!is_same_v<_Remove_cvref_t<_Fty2>, packaged_task>, int> = 0>
1223
- packaged_task(allocator_arg_t, const _Alloc& _Al, _Fty2&& _Fnarg)
1255
+ explicit packaged_task(allocator_arg_t, const _Alloc& _Al, _Fty2&& _Fnarg)
1224
1256
: _MyPromise(_STD _Make_packaged_state<_MyStateType>(_STD forward<_Fty2>(_Fnarg), _Al)) {
1225
1257
static_assert(_Is_invocable_r<_Ret, decay_t<_Fty2>&, _ArgTypes...>::value,
1226
- "The function object must be callable with _ArgTypes... and return _Ret (N4140 [futures.task.members]/2 ).");
1258
+ "The function object must be callable with _ArgTypes... and return _Ret (N5008 [futures.task.members]/3 ).");
1227
1259
}
1228
- #endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT
1229
1260
1230
1261
~packaged_task() noexcept {
1231
1262
_MyPromise._Get_state()._Abandon();
@@ -1270,7 +1301,20 @@ public:
1270
1301
void reset() { // reset to newly constructed state
1271
1302
_MyStateManagerType& _State_mgr = _MyPromise._Get_state_for_set();
1272
1303
_MyStateType& _MyState = *static_cast<_MyStateType*>(_State_mgr._Ptr());
1273
- _MyPromiseType _New_promise(new _MyStateType(_STD move(_MyState)._Get_fn()));
1304
+
1305
+ const auto _New_state_ptr = [&_MyState]() -> _Associated_state<_P_arg_type_t<_Ret>>* {
1306
+ #ifdef _CPPRTTI // TRANSITION, ABI, should not rely on RTTI
1307
+ using _Clonable_deleter_t = _Clonable_deleter_base<_P_arg_type_t<_Ret>>;
1308
+ if (const auto _Clonable_deleter = dynamic_cast<_Clonable_deleter_t*>(_MyState._Get_deleter())) {
1309
+ return _Clonable_deleter->_Move_clone(_STD move(_MyState));
1310
+ } else {
1311
+ return new _MyStateType(_STD move(_MyState)._Get_fn());
1312
+ }
1313
+ #else // ^^^ defined(_CPPRTTI) / !defined(_CPPRTTI) vvv
1314
+ return new _MyStateType(_STD move(_MyState)._Get_fn());
1315
+ #endif // ^^^ !defined(_CPPRTTI) ^^^
1316
+ }();
1317
+ _MyPromiseType _New_promise{_New_state_ptr};
1274
1318
_MyPromise._Get_state()._Abandon();
1275
1319
_MyPromise._Swap(_New_promise);
1276
1320
}
@@ -1294,11 +1338,6 @@ template <class _Fx>
1294
1338
packaged_task(_Fx) -> packaged_task<typename _Deduce_signature<_Fx>::type>;
1295
1339
#endif // _HAS_CXX17
1296
1340
1297
- #if _HAS_FUNCTION_ALLOCATOR_SUPPORT
1298
- template <class _Ty, class _Alloc>
1299
- struct uses_allocator<packaged_task<_Ty>, _Alloc> : true_type {};
1300
- #endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT
1301
-
1302
1341
_EXPORT_STD template <class _Ty>
1303
1342
void swap(packaged_task<_Ty>& _Left, packaged_task<_Ty>& _Right) noexcept {
1304
1343
_Left.swap(_Right);
0 commit comments