public GetIdentityAndDrawObject(DeathWatch deathWatch, SharePack sharePack, Func <Stream, T> stripFile) { mDeathWatch = deathWatch; SharePack = sharePack; mStripFile = stripFile; }
public static OfResourceBank.DResourceSourceDefinition <T> GetFileResource <T>(string originalPath, Func <Stream, T> stripFile, DWithFileWatcherToDispose withFileWatcherToDispose) { // weakref - don't hard link the recipient - he goes we don't have it // should only ever get 1 element var listenersForChange = new List <WeakReference <Action <Func <OfResourceBank.IdentityAndDraw <T> > > > >(); var sharePack = new SharePack(originalPath); //var getIdentityAndDrawObject = new GetIdentityAndDrawObject<T>(new DeathWatch(watcher.Dispose), originalPath, stripFile); var theLock = sharePack.mTheLock; WeakReference <GetIdentityAndDrawObject <T> > weakGetIdentity = null; Action <Option <string> > thereWasAChangeToSetPath = possibleSuccessorPath => { WeakReference <Action <Func <OfResourceBank.IdentityAndDraw <T> > > >[] relevantListenersForChange = null; lock (theLock) { possibleSuccessorPath.ForEach(successorPath => sharePack.MutablePath = successorPath); sharePack.MutableIdentity = Guid.NewGuid().ToString(); relevantListenersForChange = listenersForChange.ToArray(); //getIdentityAndDrawObject.UnderReplacement = true; } // Never, ever call back in lock we are the downsteram lock foreach (var listener in relevantListenersForChange) { Action <Func <OfResourceBank.IdentityAndDraw <T> > > func = null; if (listener.TryGetTarget(out func)) { GetIdentityAndDrawObject <T> getIdentity = null; if (weakGetIdentity.TryGetTarget(out getIdentity)) { func(getIdentity.GetIdentityAndDraw); } } } lock (theLock) { // getIdentityAndDrawObject.UnderReplacement = false; System.Threading.Monitor.PulseAll(theLock); // wake up any waiting get operation } // don't capture watcher indirectly in here, or it'll be a circular and never dispose. }; return (With( withFileWatcherToDispose( thereWasAChangeToSetPath, originalPath), watcherDispose => { var getIdentityAndDrawObject = new GetIdentityAndDrawObject <T>(new DeathWatch(watcherDispose), sharePack, stripFile); weakGetIdentity = new WeakReference <GetIdentityAndDrawObject <T> >(getIdentityAndDrawObject); return new OfResourceBank.DResourceSourceDefinition <T>( sinkReplacementOnChange => // the guy accepting the sink. { lock (theLock) { listenersForChange.Add(new WeakReference <Action <Func <OfResourceBank.IdentityAndDraw <T> > > >(sinkReplacementOnChange)); return getIdentityAndDrawObject.GetIdentityAndDraw; // deliberately capturing the deathwatch in its contents - anyone keeping the ability to read keeps the watcher alive } }); })); }