ZyX_I avatar ZyX_I committed d3d5d82

@%aurum, @%aurum/cache: Added updating rc values when cache is wiped
python/repeatedcmd: Improved handling of updating rc values: it now flushes the queue before doing calculations

Comments (0)

Files changed (4)

autoload/aurum.vim

 "▶1 
 scriptencoding utf-8
 execute frawor#Setup('0.1', {'@%aurum/repo': '5.5',
-            \                '@aurum/cache': '2.0',
+            \                '@aurum/cache': '2.3',
             \            '@%aurum/cmdutils': '4.0',})
 "▶1 getcrf
 function s:F.id(val)
     endif
     return [cbvar, repo, file]
 endfunction
-"▶1 unload
+"▶1 _unload
 function s:._unload()
     for adesc in values(s:akeys)
         call adesc.repo.functions.aremove(adesc.repo, adesc.rcid)
 "▶1 anew
 let s:abuffers={}
 let s:akeys={}
+let s:astarted=0
 function s:F.anew(buf, repo, key, func, ...)
+    if !s:astarted
+        let s:astarted=1
+        lockvar s:astarted
+        call s:_f.addwiper(s:F.aupdate)
+    endif
     if !has_key(s:abuffers, a:buf)
         let s:abuffers[a:buf]={}
     endif
                 call adesc.repo.functions.aremove(adesc.repo, adesc.rcid)
             endif
         endfor
+        augroup AuInvalidateStatusCache
+            execute 'autocmd! BufWritePost <buffer='.a:buf.'>'
+        augroup END
     endif
 endfunction
+"▶1 aupdate
+function s:F.aupdate(key)
+    call map(values(s:abuffers),
+                \'has_key(v:val, a:key) ? s:F.aget(v:val[a:key], 1) : 0')
+endfunction
 "▶1 aswitch
 let s:pexpr='map(values(v:val), '.
             \   '"v:val.repo.functions.%s(v:val.repo, v:val.rcid)")'
 endfunction
 let s:_functions+=['aurum#branch']
 "▶1
-call frawor#Lockvar(s:, '_r,abuffers,akeys')
+call frawor#Lockvar(s:, '_r,abuffers,akeys,astarted')
 " vim: ft=vim ts=4 sts=4 et fmr=▶,▲
     2.0: Removed getcrf, added _r.cache.getcbvar.
     2.1: Added _r.cache.wipe().
     2.2: Added _r.cache.getinterval().
+    2.3: Added addwiper feature.
 ftplugin/aurumlog:
     0.1: Added OpenAny and AnnotateAny mappings.
 @%aurum/drivers/common/hypsites:

plugin/aurum/cache.vim

 "▶1
 scriptencoding utf-8
 if !exists('s:_pluginloaded')
-    execute frawor#Setup('2.2', {'@/resources': '0.0',
+    execute frawor#Setup('2.3', {'@/resources': '0.0',
                 \                  '@/options': '0.0',}, 0)
     finish
 elseif s:_pluginloaded
         \}
 let s:cachebvars={}
 let s:r={}
+let s:_messages={
+            \ 'nfunc': 'Argument must be a callable function reference',
+            \ 'pldef': 'Plugin has already defined one wiper function',
+            \'dbldef': 'Function %s was already added by another plugin',
+        \}
 "▶1 bufwipeout
 function s:F.bufwipeout()
     let buf=+expand('<abuf>')
     " empty() is here only to avoid possible “Using smth as a number” error
     call map(copy(s:cachebvars), 'has_key(v:val,a:key) && '.
                 \                                  'empty(remove(v:val,a:key))')
+    call map(copy(s:wipers), 'call(v:val, [a:key], {})')
 endfunction
 "▶1 r.getinterval
 function s:r.getinterval(key)
     return s:_f.getoption(a:key.'cachetime')
 endfunction
+"▶1 addwiper feature
+let s:wipers=[]
+let s:feature={}
+function s:feature.cons(plugdict, fdict, Func)
+    if !exists('*a:Func')
+        call s:_f.throw('nfunc')
+    elseif has_key(a:fdict, 'func')
+        call s:_f.throw('pldef', string(a:fdict.func))
+    elseif index(s:wipers, a:Func)!=-1
+        call s:_f.throw('dbldef', string(a:Func))
+    endif
+    let s:wipers+=[a:Func]
+    let a:fdict.func=a:Func
+endfunction
+function s:feature.unload(plugdict, fdict)
+    if has_key(a:fdict, 'func')
+        call filter(s:wipers, 'v:val isnot# a:fdict.func')
+    endif
+endfunction
+call s:_f.newfeature('addwiper', s:feature)
 "▶1 Post cache resource
 call s:_f.postresource('cache', s:r)
 "▶1
-call frawor#Lockvar(s:, '_pluginloaded,cachebvars')
+call frawor#Lockvar(s:, '_pluginloaded,cachebvars,wipers')
 " vim: ft=vim ts=4 sts=4 et fmr=▶,▲

python/aurum/repeatedcmd.py

     pass
 
 class RepeatedCmd(object):
-    __slots__ = set(('interval', 'queue', 'lock', 'func', 'process', 'value',
-                     'args', 'kwargs', 'paused'))
+    __slots__ = set(('interval', 'queue', 'qlock', 'vlock', 'func', 'process',
+                     'value', 'args', 'kwargs', 'paused'))
     def __init__(self, interval, func, *args, **kwargs):
         self.interval = Value('f', float(interval))
         self.queue    = Queue()
-        self.lock     = Lock()
+        self.vlock    = Lock()
+        self.qlock    = Lock()
         self.func     = func
         self.args     = args
         self.kwargs   = kwargs
         self.paused   = Value('b', 0)
 
-        def procfunc(queue, lock, interval, func, args, kwargs):
+        def procfunc(queue, qlock, vlock, interval, func, args, kwargs):
             # Override default signal vim handler with system default behavior 
             # (i.e. just terminate). Without this hack process.terminate() may 
             # leave the process alive. Bad, I do not know why it leaves it alive 
             while interval.value > 0:
                 starttime = time.clock()
                 if not self.paused.value:
+                    vlock.acquire()
                     value     = func(*args, **kwargs)
-                    lock.acquire()
+                    vlock.release()
+                    qlock.acquire()
                     # If I only knew the size of func() output I would have used 
                     # Value()
                     while(not queue.empty()):
                         queue.get()
                     queue.put(value)
-                    lock.release()
+                    qlock.release()
                 try:
                     time.sleep(interval.value-(time.clock()-starttime))
                 except Exception:
                     pass
 
         self.process  = Process(target=procfunc,
-                                args=(self.queue, self.lock, self.interval,
+                                args=(self.queue, self.qlock, self.vlock,
+                                      self.interval,
                                       func, args, kwargs))
         self.process.start()
         self.value = None
     def getvalue(self):
         if not self.alive():
             raise ProcessHaltedError('Child process is not alive')
-        self.lock.acquire()
+        self.qlock.acquire()
         if self.value is None or not self.queue.empty():
             while(not self.queue.empty()):
                 self.value = self.queue.get()
-        self.lock.release()
+        self.qlock.release()
         return self.value
 
     def getcurrentvalue(self):
+        self.vlock.acquire()
+        self.qlock.acquire()
+        if self.value is None or not self.queue.empty():
+            while(not self.queue.empty()):
+                self.queue.get()
+        self.qlock.release()
         self.value = self.func(*self.args, **self.kwargs)
+        self.vlock.release()
         return self.value
 
     def alive(self):
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.