@@ -27,6 +27,7 @@ use std::cell::RefCell;
2727use std:: fmt:: { self , Debug } ;
2828
2929use crate :: order:: PartialOrder ;
30+ use crate :: progress:: Antichain ;
3031use crate :: progress:: Timestamp ;
3132use crate :: progress:: ChangeBatch ;
3233use crate :: scheduling:: Activations ;
@@ -223,6 +224,7 @@ impl Display for DowngradeError {
223224
224225impl Error for DowngradeError { }
225226
227+ /// A shared list of shared output capability buffers.
226228type CapabilityUpdates < T > = Rc < RefCell < Vec < Rc < RefCell < ChangeBatch < T > > > > > > ;
227229
228230/// An capability of an input port. Holding onto this capability will implicitly holds onto a
@@ -232,25 +234,32 @@ type CapabilityUpdates<T> = Rc<RefCell<Vec<Rc<RefCell<ChangeBatch<T>>>>>>;
232234/// This input capability supplies a `retain_for_output(self)` method which consumes the input
233235/// capability and turns it into a [Capability] for a specific output port.
234236pub struct InputCapability < T : Timestamp > {
237+ /// Output capability buffers, for use in minting capabilities.
235238 internal : CapabilityUpdates < T > ,
239+ /// Timestamp summaries for each output.
240+ summaries : Rc < RefCell < Vec < Antichain < T :: Summary > > > > ,
236241 /// A drop guard that updates the consumed capability this InputCapability refers to on drop
237242 consumed_guard : ConsumedGuard < T > ,
238243}
239244
240245impl < T : Timestamp > CapabilityTrait < T > for InputCapability < T > {
241246 fn time ( & self ) -> & T { self . time ( ) }
242247 fn valid_for_output ( & self , query_buffer : & Rc < RefCell < ChangeBatch < T > > > ) -> bool {
243- // let borrow = ;
244- self . internal . borrow ( ) . iter ( ) . any ( |rc| Rc :: ptr_eq ( rc, query_buffer) )
248+ let borrow = self . summaries . borrow ( ) ;
249+ self . internal . borrow ( ) . iter ( ) . enumerate ( ) . any ( |( index, rc) | {
250+ // To be valid, the output buffer must match and the timestamp summary needs to be the default.
251+ Rc :: ptr_eq ( rc, query_buffer) && borrow[ index] . len ( ) == 1 && borrow[ index] [ 0 ] == Default :: default ( )
252+ } )
245253 }
246254}
247255
248256impl < T : Timestamp > InputCapability < T > {
249257 /// Creates a new capability reference at `time` while incrementing (and keeping a reference to)
250258 /// the provided [`ChangeBatch`].
251- pub ( crate ) fn new ( internal : CapabilityUpdates < T > , guard : ConsumedGuard < T > ) -> Self {
259+ pub ( crate ) fn new ( internal : CapabilityUpdates < T > , summaries : Rc < RefCell < Vec < Antichain < T :: Summary > > > > , guard : ConsumedGuard < T > ) -> Self {
252260 InputCapability {
253261 internal,
262+ summaries,
254263 consumed_guard : guard,
255264 }
256265 }
@@ -270,15 +279,11 @@ impl<T: Timestamp> InputCapability<T> {
270279
271280 /// Delays capability for a specific output port.
272281 pub fn delayed_for_output ( & self , new_time : & T , output_port : usize ) -> Capability < T > {
273- // TODO : Test operator summary?
274- if !self . time ( ) . less_equal ( new_time) {
275- panic ! ( "Attempted to delay {:?} to {:?}, which is not beyond the capability's time." , self , new_time) ;
276- }
277- if output_port < self . internal . borrow ( ) . len ( ) {
282+ use crate :: progress:: timestamp:: PathSummary ;
283+ if self . summaries . borrow ( ) [ output_port] . iter ( ) . flat_map ( |summary| summary. results_in ( self . time ( ) ) ) . any ( |time| time. less_equal ( new_time) ) {
278284 Capability :: new ( new_time. clone ( ) , self . internal . borrow ( ) [ output_port] . clone ( ) )
279- }
280- else {
281- panic ! ( "Attempted to acquire a capability for a non-existent output port." ) ;
285+ } else {
286+ panic ! ( "Attempted to delay to a time ({:?}) not greater or equal to the operators input-output summary ({:?}) applied to the capabilies time ({:?})" , new_time, self . summaries. borrow( ) [ output_port] , self . time( ) ) ;
282287 }
283288 }
284289
@@ -287,18 +292,23 @@ impl<T: Timestamp> InputCapability<T> {
287292 /// This method produces an owned capability which must be dropped to release the
288293 /// capability. Users should take care that these capabilities are only stored for
289294 /// as long as they are required, as failing to drop them may result in livelock.
295+ ///
296+ /// This method panics if the timestamp summary to output zero strictly advances the time.
290297 pub fn retain ( self ) -> Capability < T > {
291- // mint(self.time.clone(), self.internal)
292298 self . retain_for_output ( 0 )
293299 }
294300
295301 /// Transforms to an owned capability for a specific output port.
302+ ///
303+ /// This method panics if the timestamp summary to `output_port` strictly advances the time.
296304 pub fn retain_for_output ( self , output_port : usize ) -> Capability < T > {
297- if output_port < self . internal . borrow ( ) . len ( ) {
298- Capability :: new ( self . time ( ) . clone ( ) , self . internal . borrow ( ) [ output_port] . clone ( ) )
305+ use crate :: progress:: timestamp:: PathSummary ;
306+ let self_time = self . time ( ) . clone ( ) ;
307+ if self . summaries . borrow ( ) [ output_port] . iter ( ) . flat_map ( |summary| summary. results_in ( & self_time) ) . any ( |time| time. less_equal ( & self_time) ) {
308+ Capability :: new ( self_time, self . internal . borrow ( ) [ output_port] . clone ( ) )
299309 }
300310 else {
301- panic ! ( "Attempted to acquire a capability for a non-existent output port." ) ;
311+ panic ! ( "Attempted to retain a time ({:?}) not greater or equal to the operators input- output summary ({:?}) applied to the capabilies time ({:?})" , self_time , self . summaries . borrow ( ) [ output_port ] , self_time ) ;
302312 }
303313 }
304314}
0 commit comments