
So I'm working on a project that uses STM to run a lot of things in parallel without the headaches of locks. So far it's working beautifully, STM rocks. But there's one snag... Sometimes I need those threads to do some IO like printing logging info. I'd like to make these IO chunks atomic with respect to one another so that the logging output isn't garbage. Since I'm using STM everywhere else, I'd love to use it for this too (instead of mixing STM and non-STM concurrency) except you can't embed IO in STM. I could just use STM vars as locks to force the atomicity, but locks are ugly and bug-prone. So what's the current best practice for doing this kind of thing? -- Live well, ~wren

Hi Wren,
maybe Twilight STM is for you:
http://hackage.haskell.org/package/twilight-stm
Sebastian
On Sat, Feb 5, 2011 at 6:46 PM, wren ng thornton
So I'm working on a project that uses STM to run a lot of things in parallel without the headaches of locks. So far it's working beautifully, STM rocks. But there's one snag...
Sometimes I need those threads to do some IO like printing logging info. I'd like to make these IO chunks atomic with respect to one another so that the logging output isn't garbage. Since I'm using STM everywhere else, I'd love to use it for this too (instead of mixing STM and non-STM concurrency) except you can't embed IO in STM.
I could just use STM vars as locks to force the atomicity, but locks are ugly and bug-prone. So what's the current best practice for doing this kind of thing?
-- Live well, ~wren
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Hi Wren, I am maintaining Twilight STM, and it seems that it might indeed solve your problem. We also use it for logging, locks, and other advanced STM stuff like inconsistency repair. If you are interested, let me know. There is a new version coming up soon, with new features and improved implementation. - Annette Am 05.02.2011 um 11:42 schrieb Sebastian Fischer:
Hi Wren,
maybe Twilight STM is for you: http://hackage.haskell.org/package/twilight-stm
Sebastian
On Sat, Feb 5, 2011 at 6:46 PM, wren ng thornton
wrote: So I'm working on a project that uses STM to run a lot of things in parallel without the headaches of locks. So far it's working beautifully, STM rocks. But there's one snag... Sometimes I need those threads to do some IO like printing logging info. I'd like to make these IO chunks atomic with respect to one another so that the logging output isn't garbage. Since I'm using STM everywhere else, I'd love to use it for this too (instead of mixing STM and non-STM concurrency) except you can't embed IO in STM.
I could just use STM vars as locks to force the atomicity, but locks are ugly and bug-prone. So what's the current best practice for doing this kind of thing?
-- Live well, ~wren
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Sat, Feb 5, 2011 at 10:46, wren ng thornton
Sometimes I need those threads to do some IO like printing logging info.
Logging is easy, especially if you don't mind a performance hit. Create an STM.TChan and throw each log message on it. Have a separate forkIO'ed process that reads off log messages and prints them. The model one step up is to generalize the logger so it forwards log messages to handlers. This way you can do logging to stdout, binary serialized logging to disk, logging to memory ring buffers, logging to databases and so on. This generalized model is used a lot in Erlang. The price however, is that you may be running into a bottleneck upon entering messages on the TChan because sadly I can't remember if it is asynchronous or synchronous when you add messages to it. It won't work for general IO either (Though perhaps it is a Writer monad). -- J.

On 05/02/2011 12:56 PM, Jesper Louis Andersen wrote:
On Sat, Feb 5, 2011 at 10:46, wren ng thornton
wrote: Sometimes I need those threads to do some IO like printing logging info.
Logging is easy, especially if you don't mind a performance hit. Create an STM.TChan and throw each log message on it. Have a separate forkIO'ed process that reads off log messages and prints them.
This is the solution I immediately thought of too. Much cleaner abstraction than grubbing around in low-level I/O implementations and such.
The price however, is that you may be running into a bottleneck upon entering messages on the TChan because sadly I can't remember if it is asynchronous or synchronous when you add messages to it.
Presumably messages added to the channel appear immediately after the transaction commits. The problem is, I think GHC's STM implementation might mean that if two transactions both try to log a message, they both get rolled back...
It won't work for general IO either (Though perhaps it is a Writer monad).
There is of course a *reason* why you can't do general I/O inside a transaction: The transaction may have seen inconsistent state, and it may be re-executed arbitrary times. Think about that before you try to shove real I/O into a transaction abstraction...

On Sat, Feb 5, 2011 at 17:13, Andrew Coppin
On 05/02/2011 12:56 PM, Jesper Louis Andersen wrote:
Presumably messages added to the channel appear immediately after the transaction commits. The problem is, I think GHC's STM implementation might mean that if two transactions both try to log a message, they both get rolled back...
Yes, this is the performance caveat I was hinting at. When logging becomes heavy and transactions are *not* completing, you will have transaction retries due to the logging. If the transaction completes however, it is not that much of a problem. -- J.

On Sat, Feb 5, 2011 at 8:19 AM, Jesper Louis Andersen
On Sat, Feb 5, 2011 at 17:13, Andrew Coppin
wrote: On 05/02/2011 12:56 PM, Jesper Louis Andersen wrote:
Presumably messages added to the channel appear immediately after the transaction commits. The problem is, I think GHC's STM implementation might mean that if two transactions both try to log a message, they both get rolled back...
Yes, this is the performance caveat I was hinting at. When logging becomes heavy and transactions are *not* completing, you will have transaction retries due to the logging. If the transaction completes however, it is not that much of a problem.
I recall reading that clojure has a concept of associative combination. If you can declare that certain operations are associative then the runtime doesn't have to care if they get out of order.

On Feb 5, 2011, at 2:37 PM, Evan Laforge wrote:
I recall reading that clojure has a concept of associative combination. If you can declare that certain operations are associative then the runtime doesn't have to care if they get out of order.
I think that you're thinking about the "commute" operation: http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/commute There's more discussion elsewhere on the web, including here: http://squirrel.pl/blog/2010/07/13/clojure-alter-vs-commute/ Cheers, Sterl

There's the stm-io-hooks [1] package but it looks like it hasn't been
updated in a while.
-deech
[1]http://hackage.haskell.org/package/stm-io-hooks
On Sat, Feb 5, 2011 at 3:46 AM, wren ng thornton
So I'm working on a project that uses STM to run a lot of things in parallel without the headaches of locks. So far it's working beautifully, STM rocks. But there's one snag...
Sometimes I need those threads to do some IO like printing logging info. I'd like to make these IO chunks atomic with respect to one another so that the logging output isn't garbage. Since I'm using STM everywhere else, I'd love to use it for this too (instead of mixing STM and non-STM concurrency) except you can't embed IO in STM.
I could just use STM vars as locks to force the atomicity, but locks are ugly and bug-prone. So what's the current best practice for doing this kind of thing?
-- Live well, ~wren
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
participants (8)
-
aditya siram
-
Andrew Coppin
-
Annette Bieniusa
-
Evan Laforge
-
Jesper Louis Andersen
-
Sebastian Fischer
-
Sterling Clover
-
wren ng thornton