What you say about caching, #filter, and modifying the searchList is corr=
I forget about them. However, I still maintain that if you avoid using th=
features, it should be possible to share templates concurrently between=20
I'll look into the concurrency issue in the caching framework when I get =
On December 2, 2002 11:23 am, Mike Orr wrote:
> > On December 1, 2002 07:43 pm, Michael Engelhart wrote:
> > > I was just looking through the archives to see how to use FunFormK=
> > > with Cheetah and saw a post that said that Cheetah is not thread sa=
> > > Is this true??
> Cheetah is not thread safe (meaning you can't share a template instance
> between threads without synchronization) for many reasons, but the
> biggest reason is the searchList. One thread would set its searchList
> values, interfering with the other thread's values. Using instance
> variables (t.myVar) instead of the searchList has the same
> So you can't put a Template instance in a global variable, a class
> variable, or a cache of templates, unless you guarantee it won't be cal=
> concurrently. But you can put a precompiled Template class in all thos=
> places, and instantiate it in each thread. You can also use a subclass
> to customize aspects of the Template class. Or use a factory function
> that builds and returns a Template instance according to your custom
> I also would avoid Webware's .canBeThreaded(). You may be able to find
> a safe way to use it with Cheetah, but it would be a lot of work and
> little benefit. Instead, use Webware's wonderful servlet caching, and
> then Cheetah won't even be invoked at all until Webware unexpires the
> cached servlet.
> On Sun, Dec 01, 2002 at 11:32:37PM -0800, Tavis Rudd wrote:
> > I won't go into the specifics of how you could manage the request-rel=
> > state external to the servlet instance, aside from pointing out that =
> > need to pass the Transaction object on to all methods and contained
> > objects that need access to this state.
> For template-servlets, Webware already passes the transaction to
> .awake(), .respond() and .sleep(). You'd just need to pass it through
> to any sub-method you call.
> > However, like Webkit.Page, the Cheetah.Servlet baseclass provides som=
> > convience methods that return the current transactions' request,
> > response, session, etc (i.e. internally stored request-related state)=
> > If you declare your servlets to be threadsafe, by overriding the
> > canBeThreaded() method, you need to avoid using these methods. You'll
> > also need to avoid the '#set global' directive.
> I think you need to avoid more than that. We've always said Cheetah is
> non thread safe pending an audit of what exactly is safe and what is
> not. Here's a tentative audit, although since I haven't written any
> multithreaded programs or looked through all the Cheetah source, it may
> be incomplete.
> Concurrency problems happen when one thread access changing state data
> in two non-atomic (=3Dseparate) operations in one thread, while another
> thread modifies the data between the two. If the values remain constan=
> after .__init__(), there's no problem. There's also no problem if you
> use an external lock/mutex between sets of operations where another
> thread must not modify the data. Thus, the following changing state is
> incompatible with concurrency:
> ** Modifying searchList variables, or modifying instance attributes for
> the same effect.
> ** Adding/deleting containers on the searchList; i.e.,
> .searchList().insert(0, myContainer)
> ** #filter, which modifies ._currentFilter .
> ** "#set global", which modifies ._globalSetVars .
> ** #errorCatcher , which modifies ._errorCatcher .
> ** #compiler-settings . Maybe this safe after all, I'm not sure.
> ** Placeholder caching: $* (all variations) and #cache . Each cache
> item has three state values which must be synchronized:
> ._cacheData['123'] # Cache item with id '123'
> .__cache123__refreshTime # Float, when to refresh.
> ._cacheIndex['cache1'] # I don't know what this is for, but the
> # value is the cache ID ('123').
> Added to this, the template currently compiles to
> ._cacheData.has_key('123') ... ._cacheData['123'] , so if another threa=
> deletes the item between the two, you'll get an error. This could be
> avoided via "try: ... except KeyError ..." at the cost of some overhead
> (overhead =3D what we're trying to avoid by using caching), but there's=
> way to synchronize all three state values in one operation.
> I was curious why we're using dictionaries for two state pieces and
> an attribute for the third, but Tavis said it's faster that way.
> Perhaps Cheetah's caching framework is flawed because it's incompatible
> with concurrency. It works for serialized access, one fill after the
> other, but it doesn't work with concurrent access, two threads sharing
> an instance and taking advantage of each other's placeholder cache.
> Tavis has talked about revamping the caching framework someday, but I'm
> not sure whether making it atomic is part of the plan.