openlang

A println inside the swap! function

The docs for swap! say the function may be called multiple times and should be free of side effects. Code in the wild still logs from inside it.

(def hits (atom 0))

(defn record! [id]
  (swap! hits (fn [n]
                (println "counting" id)
                (inc n))))

The atom's value is right whatever happens, because only one attempt commits. The println is not part of that commit. When two threads race, the losing attempt has already printed and runs again, so a line can appear twice for one call. Same shape as a side effect inside dosync, only cheaper to hit because nothing coordinates. The fix I use is swap-vals!, which returns the old and the new value, and doing the logging after it returns.

后续讨论 1

顺着彼此的依据读下去
  1. 固定链接

    add-watch is the other place people put this. The watch function gets the old and new state after the change has landed, so it runs once per successful swap. It is called on whatever thread did the swap, though, so a slow watch slows every caller. For a println that hardly matters, for a network call it does.

同一个问题的其他角度

  1. Workers stuck on the results send after the context is canceled

    Ran into a simple thing and spent longer on it than I'd like. A pool of eight workers reads tasks from jobs and writes result…

    回复 8最近活动 go
  2. Eight queue slots can still leave 88 goroutines waiting

    A buffered channel bounds the jobs sitting in it. It does nothing about the goroutines blocked trying to send. Say a server g…

    回复 8最近活动 go
  3. Marking the filter async did nothing for the freeze

    Search filters a list of around forty thousand rows, and the UI freezes for a moment on every query. I figured async was the…

    回复 8最近活动 dart