@@ -477,6 +477,11 @@ struct _Acquire final {
477477 template <typename Arg, typename Errors>
478478 using ErrorsFrom = Errors;
479479
480+ // TODO(benh): nothing can actually compose with anything else
481+ // because it depends one what gets composed with this. Alas, we
482+ // need to change the way 'Reschedule()' works here to take the
483+ // eventual that it wants to run so that we can properly check
484+ // that things compose correctly.
480485 template <typename Downstream>
481486 static constexpr bool CanCompose = true ;
482487
@@ -559,6 +564,11 @@ struct _Release final {
559564 template <typename Arg, typename Errors>
560565 using ErrorsFrom = Errors;
561566
567+ // TODO(benh): nothing can actually compose with anything else
568+ // because it depends one what gets composed with this. Alas, we
569+ // need to change the way 'Reschedule()' works here to take the
570+ // eventual that it wants to run so that we can properly check
571+ // that things compose correctly.
562572 template <typename Downstream>
563573 static constexpr bool CanCompose = true ;
564574
@@ -792,16 +802,21 @@ struct _Wait final {
792802 template <typename Arg, typename Errors>
793803 using ErrorsFrom = Errors;
794804
795- template < typename Arg, typename K>
796- auto k (K k) && {
797- return Continuation<K, F_, Arg>( std::move (k), lock_, std::move (f_));
798- }
799-
805+ // TODO(benh): nothing can actually compose with anything else
806+ // because it depends one what gets composed with this. Alas, we
807+ // need to change the way 'Reschedule()' works here to take the
808+ // eventual that it wants to run so that we can properly check
809+ // that things compose correctly.
800810 template <typename Downstream>
801811 static constexpr bool CanCompose = true ;
802812
803813 using Expects = StreamOrValue;
804814
815+ template <typename Arg, typename K>
816+ auto k (K k) && {
817+ return Continuation<K, F_, Arg>(std::move (k), lock_, std::move (f_));
818+ }
819+
805820 Lock* lock_;
806821 F_ f_;
807822 };
@@ -828,15 +843,45 @@ template <typename F>
828843
829844// //////////////////////////////////////////////////////////////////////
830845
846+ struct _Synchronized final {
847+ template <typename E_>
848+ struct Composable final {
849+ // NOTE: declaring these here to use them to make type aliases.
850+ Lock* lock_;
851+ E_ e_;
852+
853+ using Composed_ =
854+ decltype (Acquire(lock_) >> std::move (e_) >> Release(lock_));
855+
856+ template <typename Arg>
857+ using ValueFrom = typename Composed_::template ValueFrom<Arg>;
858+
859+ template <typename Arg, typename Errors>
860+ using ErrorsFrom = typename Composed_::template ErrorsFrom<Arg, Errors>;
861+
862+ template <typename Downstream>
863+ static constexpr bool CanCompose = E_::template CanCompose<Downstream>;
864+
865+ using Expects = typename E_::Expects;
866+
867+ template <typename Arg, typename K>
868+ auto k (K k) && {
869+ return Build<Arg>(
870+ Acquire (lock_) >> std::move (e_) >> Release (lock_),
871+ std::move (k));
872+ }
873+ };
874+ };
875+
876+ // //////////////////////////////////////////////////////////////////////
877+
831878class Synchronizable {
832879 public:
833880 virtual ~Synchronizable () = default ;
834881
835882 template <typename E>
836883 [[nodiscard]] auto Synchronized (E e) {
837- return Acquire (&lock_)
838- >> std::move (e)
839- >> Release (&lock_);
884+ return _Synchronized::Composable<E>{&lock_, std::move (e)};
840885 }
841886
842887 template <typename F>
0 commit comments