I disagree that the code can't know what will switch with green threads. They switch on I/O and when explicitly requested. An example of using this to get rid of concurrency control: http://www.underengineering.com/2014/05/22/DIY-NoSql/
If you want to make sure that there are no context switching in certain part of your code, you can do it ASSERT-style, something like:
# enable this only if you use atomic, so a new module that should be imported before gevent
in_transaction = False
if __debug__:
import greenlet
old_switch=greenlet.greenlet.switch
class _greenlet(greenlet.greenlet):
def switch(*args, **kwargs):
if in_transaction:
raise Exception('Switching context during / atomic')
old_switch(*args, **kwargs)
setattr(greenlet, 'greenlet', _greenlet)
@contextmanager
def atomic():
"""
Ensure that a function or a block of code is atomic, raise exception if it's not
Usage:
@atomic()
def myTransaction(...):
...
or
with atomic():
...
"""
global in_transaction
in_transaction = True
yield
in_transaction = False