@@ -847,44 +847,65 @@ static_assert(sizeof(ActiveActorStatus) == ACTIVE_ACTOR_STATUS_SIZE,
847
847
// / exist yet. As a result, the subset of rules that currently apply
848
848
// / are (1), (3), (5), (6).
849
849
class DefaultActorImpl : public HeapObject {
850
+ struct Header {
850
851
#if SWIFT_CONCURRENCY_ACTORS_AS_LOCKS
851
- // If actors are locks, we don't need to maintain any extra bookkeeping in the
852
- // ActiveActorStatus since all threads which are contending will block
853
- // synchronously, no job queue is needed and the lock will handle all priority
854
- // escalation logic
855
- Mutex drainLock;
852
+ // If actors are locks, we don't need to maintain any extra bookkeeping in the
853
+ // ActiveActorStatus since all threads which are contending will block
854
+ // synchronously, no job queue is needed and the lock will handle all priority
855
+ // escalation logic
856
+ Mutex drainLock;
856
857
#else
857
- // Note: There is some padding that is added here by the compiler in order to
858
- // enforce alignment. This is space that is available for us to use in
859
- // the future
860
- alignas (sizeof (ActiveActorStatus)) char StatusStorage[sizeof(ActiveActorStatus)];
858
+ // Note: There is some padding that is added here by the compiler in order to
859
+ // enforce alignment. This is space that is available for us to use in
860
+ // the future
861
+ alignas (sizeof (ActiveActorStatus)) char StatusStorage[sizeof(ActiveActorStatus)];
862
+ #endif
863
+ // TODO (rokhinip): Make this a flagset
864
+ bool isDistributedRemoteActor;
865
+ } header;
861
866
867
+ #if !SWIFT_CONCURRENCY_ACTORS_AS_LOCKS
862
868
using SimpleQueue = swift::SimpleQueue<Job *, JobQueueTraits>;
863
869
using PriorityQueue = swift::PriorityQueue<Job *, JobQueueTraits>;
864
870
865
- // When enqueued, jobs are atomically added to a linked list with the head
866
- // stored inside ActiveActorStatus. This list contains jobs in the LIFO order
867
- // regardless of their priorities.
868
- //
869
- // After that processing thread collects them and adds to the
870
- // `prioritisedJobs` while holding the actor lock.
871
- //
872
- // TODO: Move this to the end of the actor memory to minimise false sharing
873
- //
874
- PriorityQueue prioritisedJobs;
871
+ struct Footer {
872
+ // When enqueued, jobs are atomically added to a linked list with the head
873
+ // stored inside ActiveActorStatus. This list contains jobs in the LIFO order
874
+ // regardless of their priorities.
875
+ //
876
+ // After that processing thread collects them and adds to the
877
+ // `prioritisedJobs` while holding the actor lock.
878
+ //
879
+ PriorityQueue prioritisedJobs;
880
+ };
881
+
882
+ struct Padding {
883
+ enum {
884
+ // Available space
885
+ x1 = (int )(sizeof (void *) * NumWords_DefaultActor),
886
+ // ... subtracting size of footer
887
+ x2 = x1 - (int )sizeof (Footer),
888
+ // ... ensuring footer is aligned
889
+ x3 = x2 - (int )(x2 % alignof (Footer)),
890
+ // ... subtracting size of header
891
+ x4 = x3 - (int )sizeof (Header),
892
+ // ... subtracting padding before header
893
+ size = x4 - (int )((alignof (Header) - sizeof (HeapObject) % alignof (Header)) % alignof (Header))
894
+ };
895
+ };
896
+ char padding[Padding::size];
897
+ Footer footer;
875
898
#endif
876
- // TODO (rokhinip): Make this a flagset
877
- bool isDistributedRemoteActor;
878
899
879
900
public:
880
901
// / Properly construct an actor, except for the heap header.
881
902
void initialize (bool isDistributedRemote = false ) {
882
- this ->isDistributedRemoteActor = isDistributedRemote;
903
+ this ->header . isDistributedRemoteActor = isDistributedRemote;
883
904
#if SWIFT_CONCURRENCY_ACTORS_AS_LOCKS
884
- new (&this ->drainLock ) Mutex ();
905
+ new (&this ->header . drainLock ) Mutex ();
885
906
#else
886
907
_status ().store (ActiveActorStatus (), std::memory_order_relaxed);
887
- new (&this ->prioritisedJobs ) PriorityQueue ();
908
+ new (&this ->footer . prioritisedJobs ) PriorityQueue ();
888
909
#endif
889
910
SWIFT_TASK_DEBUG_LOG (" Creating default actor %p" , this );
890
911
concurrency::trace::actor_create (this );
@@ -924,20 +945,25 @@ class DefaultActorImpl : public HeapObject {
924
945
925
946
#if !SWIFT_CONCURRENCY_ACTORS_AS_LOCKS
926
947
swift::atomic<ActiveActorStatus> &_status () {
927
- return reinterpret_cast <swift::atomic<ActiveActorStatus>&> (this ->StatusStorage );
948
+ return reinterpret_cast <swift::atomic<ActiveActorStatus>&> (this ->header . StatusStorage );
928
949
}
929
950
930
951
const swift::atomic<ActiveActorStatus> &_status () const {
931
- return reinterpret_cast <const swift::atomic<ActiveActorStatus>&> (this ->StatusStorage );
952
+ return reinterpret_cast <const swift::atomic<ActiveActorStatus>&> (this ->header . StatusStorage );
932
953
}
933
954
934
955
// Only for static assert use below, not for actual use otherwise
935
956
static constexpr size_t offsetOfActiveActorStatus () {
936
957
#pragma clang diagnostic push
937
958
#pragma clang diagnostic ignored "-Winvalid-offsetof"
938
- return offsetof (DefaultActorImpl, StatusStorage);
959
+ return offsetof (DefaultActorImpl, header. StatusStorage );
939
960
#pragma clang diagnostic pop
940
961
}
962
+
963
+ PriorityQueue &_prioritisedJobs () {
964
+ return footer.prioritisedJobs ;
965
+ }
966
+
941
967
#endif /* !SWIFT_CONCURRENCY_ACTORS_AS_LOCKS */
942
968
943
969
private:
@@ -1266,7 +1292,7 @@ void DefaultActorImpl::processJobs() {
1266
1292
auto job = jobs.head ;
1267
1293
while (job) {
1268
1294
auto next = getNextJob (job);
1269
- prioritisedJobs .enqueue (job);
1295
+ _prioritisedJobs () .enqueue (job);
1270
1296
job = next;
1271
1297
}
1272
1298
}
@@ -1276,8 +1302,8 @@ Job *DefaultActorImpl::drainOne() {
1276
1302
SWIFT_TASK_DEBUG_LOG (" Draining one job from default actor %p" , this );
1277
1303
1278
1304
processJobs ();
1279
- traceJobQueue (this , prioritisedJobs .peek ());
1280
- auto firstJob = prioritisedJobs .dequeue ();
1305
+ traceJobQueue (this , _prioritisedJobs () .peek ());
1306
+ auto firstJob = _prioritisedJobs () .dequeue ();
1281
1307
if (!firstJob) {
1282
1308
SWIFT_TASK_DEBUG_LOG (" No jobs to drain on actor %p" , this );
1283
1309
} else {
@@ -1522,7 +1548,7 @@ retry:;
1522
1548
std::memory_order_relaxed)) {
1523
1549
_swift_tsan_acquire (this );
1524
1550
if (assertNoJobs) {
1525
- assert (prioritisedJobs .empty ());
1551
+ assert (_prioritisedJobs () .empty ());
1526
1552
}
1527
1553
traceActorStateTransition (this , oldState, newState, distributedActorIsRemote);
1528
1554
return true ;
@@ -1573,7 +1599,7 @@ bool DefaultActorImpl::unlock(bool forceUnlock)
1573
1599
1574
1600
auto newState = oldState;
1575
1601
// Lock is still held at this point, so it is safe to access prioritisedJobs
1576
- if (!prioritisedJobs .empty () || oldState.getFirstUnprioritisedJob ()) {
1602
+ if (!_prioritisedJobs () .empty () || oldState.getFirstUnprioritisedJob ()) {
1577
1603
// There is work left to do, don't unlock the actor
1578
1604
if (!forceUnlock) {
1579
1605
SWIFT_TASK_DEBUG_LOG (" Unlock-ing actor %p failed" , this );
@@ -2094,5 +2120,5 @@ bool swift::swift_distributed_actor_is_remote(HeapObject *_actor) {
2094
2120
}
2095
2121
2096
2122
bool DefaultActorImpl::isDistributedRemote () {
2097
- return this ->isDistributedRemoteActor ;
2123
+ return this ->header . isDistributedRemoteActor ;
2098
2124
}
0 commit comments