| //===--- ActorIsolation.h - Actor isolation ---------------------*- C++ -*-===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See https://swift.org/LICENSE.txt for license information |
| // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file provides a description of actor isolation state. |
| // |
| //===----------------------------------------------------------------------===// |
| #ifndef SWIFT_AST_ACTORISOLATIONSTATE_H |
| #define SWIFT_AST_ACTORISOLATIONSTATE_H |
| |
| #include "swift/AST/Type.h" |
| #include "llvm/ADT/Hashing.h" |
| |
| namespace llvm { |
| class raw_ostream; |
| } |
| |
| namespace swift { |
| class ClassDecl; |
| class SubstitutionMap; |
| class Type; |
| |
| /// Determine whether the given types are (canonically) equal, declared here |
| /// to avoid having to include Types.h. |
| bool areTypesEqual(Type type1, Type type2); |
| |
| /// Describes the actor isolation of a given declaration, which determines |
| /// the actors with which it can interact. |
| class ActorIsolation { |
| public: |
| enum Kind { |
| /// The actor isolation has not been specified. It is assumed to be |
| /// unsafe to interact with this declaration from any actor. |
| Unspecified = 0, |
| /// The declaration is isolated to the instance of an actor class. |
| /// For example, a mutable stored property or synchronous function within |
| /// the actor is isolated to the instance of that actor. |
| ActorInstance, |
| /// The declaration is explicitly specified to be independent of any actor, |
| /// meaning that it can be used from any actor but is also unable to |
| /// refer to the isolated state of any given actor. |
| Independent, |
| /// The declaration is explicitly specified to be independent of any actor, |
| /// but the programmer promises to protect the declaration from concurrent |
| /// accesses manually. Thus, it is okay if this declaration is a mutable |
| /// variable that creates storage. |
| IndependentUnsafe, |
| /// The declaration is isolated to a global actor. It can refer to other |
| /// entities with the same global actor. |
| GlobalActor, |
| }; |
| |
| private: |
| Kind kind; |
| union { |
| ClassDecl *actor; |
| Type globalActor; |
| void *pointer; |
| }; |
| |
| ActorIsolation(Kind kind, ClassDecl *actor) : kind(kind), actor(actor) { } |
| ActorIsolation(Kind kind, Type globalActor) |
| : kind(kind), globalActor(globalActor) { } |
| |
| public: |
| static ActorIsolation forUnspecified() { |
| return ActorIsolation(Unspecified, nullptr); |
| } |
| |
| static ActorIsolation forIndependent(ActorIndependentKind indepKind) { |
| ActorIsolation::Kind isoKind; |
| switch (indepKind) { |
| case ActorIndependentKind::Safe: |
| isoKind = Independent; |
| break; |
| |
| case ActorIndependentKind::Unsafe: |
| isoKind = IndependentUnsafe; |
| break; |
| } |
| return ActorIsolation(isoKind, nullptr); |
| } |
| |
| static ActorIsolation forActorInstance(ClassDecl *actor) { |
| return ActorIsolation(ActorInstance, actor); |
| } |
| |
| static ActorIsolation forGlobalActor(Type globalActor) { |
| return ActorIsolation(GlobalActor, globalActor); |
| } |
| |
| Kind getKind() const { return kind; } |
| |
| operator Kind() const { return getKind(); } |
| |
| bool isUnspecified() const { return kind == Unspecified; } |
| |
| ClassDecl *getActor() const { |
| assert(getKind() == ActorInstance); |
| return actor; |
| } |
| |
| Type getGlobalActor() const { |
| assert(getKind() == GlobalActor); |
| return globalActor; |
| } |
| |
| /// Determine whether this isolation will require substitution to be |
| /// evaluated. |
| bool requiresSubstitution() const; |
| |
| /// Substitute into types within the actor isolation. |
| ActorIsolation subst(SubstitutionMap subs) const; |
| |
| friend bool operator==(const ActorIsolation &lhs, |
| const ActorIsolation &rhs) { |
| if (lhs.kind != rhs.kind) |
| return false; |
| |
| switch (lhs.kind) { |
| case Independent: |
| case IndependentUnsafe: |
| case Unspecified: |
| return true; |
| |
| case ActorInstance: |
| return lhs.actor == rhs.actor; |
| |
| case GlobalActor: |
| return areTypesEqual(lhs.globalActor, rhs.globalActor); |
| } |
| } |
| |
| friend bool operator!=(const ActorIsolation &lhs, |
| const ActorIsolation &rhs) { |
| return !(lhs == rhs); |
| } |
| |
| friend llvm::hash_code hash_value(const ActorIsolation &state) { |
| return llvm::hash_combine(state.kind, state.pointer); |
| } |
| }; |
| |
| /// Determine how the given value declaration is isolated. |
| ActorIsolation getActorIsolation(ValueDecl *value); |
| |
| void simple_display(llvm::raw_ostream &out, const ActorIsolation &state); |
| |
| } // end namespace swift |
| |
| #endif /* SWIFT_AST_ACTORISOLATIONSTATE_H */ |