decorators.py 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. #! /usr/bin/env python
  2. # -*- encoding: utf-8 -*-
  3. # vim:fenc=utf-8:
  4. from threading import Thread
  5. from functools import wraps
  6. from fabric.api import parallel as fabric_parallel
  7. from mico.util.mutex import Mutex
  8. parallel = fabric_parallel
  9. def async(func):
  10. """Function decorator, intended to make "func" run in a separate
  11. thread (asynchronously).
  12. Example:
  13. .. code-block:: python
  14. @async
  15. def task1():
  16. do_something
  17. @async
  18. def task2():
  19. do_something_too
  20. t1 = task1()
  21. t2 = task2()
  22. t1.join()
  23. t2.join()
  24. """
  25. @wraps(func)
  26. def _inner(*args, **kwargs):
  27. func_th = Thread(target = func, args = args, kwargs = kwargs)
  28. func_th.start()
  29. return func_th
  30. return _inner
  31. def serial(func):
  32. """Function decorator, intended to make "func" wait for threading async
  33. finished.
  34. Example:
  35. .. code-block:: python
  36. @async
  37. def task1():
  38. do_something
  39. @async
  40. def task2():
  41. do_something_too
  42. @serial
  43. def task3():
  44. do_something_when_task1_and_task2_finished()
  45. t1 = task1()
  46. t2 = task2()
  47. t3 = task3() # Only runs when task1 and task2 finished.
  48. """
  49. @wraps(func)
  50. def _inner(*args, **kwargs):
  51. import threading, time
  52. while threading.activeCount() > 1:
  53. time.sleep(1)
  54. return func(*args, **kwargs)
  55. return _inner
  56. def sync(f):
  57. """Decorator to synchronize a function while running in asynchronous
  58. mode. Let's suppose that you have a number of tasks decorated by
  59. ``@async``, but you need to ensure that one common action is
  60. synchronized over all of them, then ``@sync`` is for you.
  61. .. note:: The ``@sync`` decorator is radically different of ``@serial``.
  62. While ``@serial`` waits for every thread to be done, ``@sync`` just only
  63. ensure that the decorated function is calling once a time.
  64. """
  65. def _f(*args, **kw):
  66. with Mutex.get_mutex(f.__name__):
  67. return f(*args, **kw)
  68. return _f