summaryrefslogtreecommitdiff
path: root/tex/context/base/luat-cbk.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/luat-cbk.lua')
-rw-r--r--tex/context/base/luat-cbk.lua640
1 files changed, 320 insertions, 320 deletions
diff --git a/tex/context/base/luat-cbk.lua b/tex/context/base/luat-cbk.lua
index 5aa12005b..4a88cfed7 100644
--- a/tex/context/base/luat-cbk.lua
+++ b/tex/context/base/luat-cbk.lua
@@ -1,320 +1,320 @@
-if not modules then modules = { } end modules ['luat-cbk'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local insert, remove, find, format = table.insert, table.remove, string.find, string.format
-local collectgarbage, type, next = collectgarbage, type, next
-local round = math.round
-local sortedhash, tohash = table.sortedhash, table.tohash
-
-local trace_checking = false trackers.register("memory.checking", function(v) trace_checking = v end)
-
-local report_callbacks = logs.reporter("system","callbacks")
-local report_memory = logs.reporter("system","memory")
-
---[[ldx--
-<p>Callbacks are the real asset of <l n='luatex'/>. They permit you to hook
-your own code into the <l n='tex'/> engine. Here we implement a few handy
-auxiliary functions.</p>
---ldx]]--
-
-callbacks = callbacks or { }
-local callbacks = callbacks
-
---[[ldx--
-<p>When you (temporarily) want to install a callback function, and after a
-while wants to revert to the original one, you can use the following two
-functions.</p>
---ldx]]--
-
-local trace_callbacks = false trackers.register("system.callbacks", function(v) trace_callbacks = v end)
-local trace_calls = false -- only used when analyzing performance and initializations
-
-local register_callback = callback.register
-local find_callback = callback.find
-local list_callbacks = callback.list
-
-local frozen, stack, list = { }, { }, callbacks.list
-
-if not list then -- otherwise counters get reset
-
- list = utilities.storage.allocate(list_callbacks())
-
- for k, _ in next, list do
- list[k] = 0
- end
-
- callbacks.list = list
-
-end
-
-local delayed = tohash {
- "buildpage_filter",
-}
-
-
-if trace_calls then
-
- local functions = { }
- local original = register_callback
-
- register_callback = function(name,func)
- if type(func) == "function" then
- if functions[name] then
- functions[name] = func
- return find_callback(name)
- else
- functions[name] = func
- local cnuf = function(...)
- list[name] = list[name] + 1
- return functions[name](...)
- end
- return original(name,cnuf)
- end
- else
- return original(name,func)
- end
- end
-
-end
-
-local function frozen_message(what,name)
- report_callbacks("not %s frozen %a to %a",what,name,frozen[name])
-end
-
-local function frozen_callback(name)
- return nil, format("callback '%s' is frozen to '%s'",name,frozen[name]) -- no formatter yet
-end
-
-local function state(name)
- local f = find_callback(name)
- if f == false then
- return "disabled"
- elseif f then
- return "enabled"
- else
- return "undefined"
- end
-end
-
-function callbacks.known(name)
- return list[name]
-end
-
-function callbacks.report()
- for name, _ in sortedhash(list) do
- local str = frozen[name]
- if str then
- report_callbacks("%s: %s -> %s",state(name),name,str)
- else
- report_callbacks("%s: %s",state(name),name)
- end
- end
-end
-
-function callbacks.freeze(name,freeze)
- freeze = type(freeze) == "string" and freeze
- if find(name,"%*") then
- local pattern = name
- for name, _ in next, list do
- if find(name,pattern) then
- frozen[name] = freeze or frozen[name] or "frozen"
- end
- end
- else
- frozen[name] = freeze or frozen[name] or "frozen"
- end
-end
-
-function callbacks.register(name,func,freeze)
- if frozen[name] then
- if trace_callbacks then
- frozen_message("registering",name)
- end
- return frozen_callback(name)
- elseif freeze then
- frozen[name] = type(freeze) == "string" and freeze or "registered"
- end
- if delayed[name] and environment.initex then
- return nil
- end
- return register_callback(name,func)
-end
-
-function callback.register(name,func) -- original
- if not frozen[name] then
- return register_callback(name,func)
- elseif trace_callbacks then
- frozen_message("registering",name)
- end
- return frozen_callback(name)
-end
-
-function callbacks.push(name,func)
- if not frozen[name] then
- local sn = stack[name]
- if not sn then
- sn = { }
- stack[name] = sn
- end
- insert(sn,find_callback(name))
- register_callback(name, func)
- elseif trace_callbacks then
- frozen_message("pushing",name)
- end
-end
-
-function callbacks.pop(name)
- if not frozen[name] then
- local sn = stack[name]
- if not sn or #sn == 0 then
- -- some error
- register_callback(name, nil) -- ! really needed
- else
- -- this fails: register_callback(name, remove(stack[name]))
- local func = remove(sn)
- register_callback(name, func)
- end
- end
-end
-
-if trace_calls then
- statistics.register("callback details", function()
- local t = { } -- todo: pass function to register and quit at nil
- for name, n in sortedhash(list) do
- if n > 0 then
- t[#t+1] = format("%s -> %s",name,n)
- end
- end
- return t
- end)
-end
-
--- -- somehow crashes later on
---
--- callbacks.freeze("find_.*_file","finding file")
--- callbacks.freeze("read_.*_file","reading file")
--- callbacks.freeze("open_.*_file","opening file")
-
---[[ldx--
-<p>The simple case is to remove the callback:</p>
-
-<code>
-callbacks.push('linebreak_filter')
-... some actions ...
-callbacks.pop('linebreak_filter')
-</code>
-
-<p>Often, in such case, another callback or a macro call will pop
-the original.</p>
-
-<p>In practice one will install a new handler, like in:</p>
-
-<code>
-callbacks.push('linebreak_filter', function(...)
- return something_done(...)
-end)
-</code>
-
-<p>Even more interesting is:</p>
-
-<code>
-callbacks.push('linebreak_filter', function(...)
- callbacks.pop('linebreak_filter')
- return something_done(...)
-end)
-</code>
-
-<p>This does a one-shot.</p>
---ldx]]--
-
---[[ldx--
-<p>Callbacks may result in <l n='lua'/> doing some hard work
-which takes time and above all resourses. Sometimes it makes
-sense to disable or tune the garbage collector in order to
-keep the use of resources acceptable.</p>
-
-<p>At some point in the development we did some tests with counting
-nodes (in this case 121049).</p>
-
-<table>
-<tr><td>setstepmul</td><td>seconds</td><td>megabytes</td></tr>
-<tr><td>200</td><td>24.0</td><td>80.5</td></tr>
-<tr><td>175</td><td>21.0</td><td>78.2</td></tr>
-<tr><td>150</td><td>22.0</td><td>74.6</td></tr>
-<tr><td>160</td><td>22.0</td><td>74.6</td></tr>
-<tr><td>165</td><td>21.0</td><td>77.6</td></tr>
-<tr><td>125</td><td>21.5</td><td>89.2</td></tr>
-<tr><td>100</td><td>21.5</td><td>88.4</td></tr>
-</table>
-
-<p>The following code is kind of experimental. In the documents
-that describe the development of <l n='luatex'/> we report
-on speed tests. One observation is thta it sometimes helps to
-restart the collector. Okay, experimental code has been removed,
-because messing aroudn with the gc is too unpredictable.</p>
---ldx]]--
-
--- For the moment we keep this here and not in util-gbc.lua or so.
-
-utilities = utilities or { }
-utilities.garbagecollector = utilities.garbagecollector or { }
-local garbagecollector = utilities.garbagecollector
-
-garbagecollector.enabled = false -- could become a directive
-garbagecollector.criterium = 4*1024*1024
-
--- Lua allocates up to 12 times the amount of memory needed for
--- handling a string, and for large binary chunks (like chinese otf
--- files) we get a prominent memory consumption. Even when a variable
--- is nilled, there is some delay in freeing the associated memory (the
--- hashed string) because if we do the same thing directly afterwards,
--- we see only a slight increase in memory. For that reason it makes
--- sense to do a collector pass after a huge file.
---
--- test file:
---
--- function test()
--- local b = collectgarbage("count")
--- local s = io.loaddata("some font table, e.g. a big tmc file")
--- local a = collectgarbage("count")
--- print(">>> STATUS",b,a,a-b,#s,1000*(a-b)/#s)
--- end
---
--- test() test() test() test() collectgarbage("collect") test() test() test() test()
---
--- As a result of this, LuaTeX now uses an optimized version of f:read("*a"),
--- one that does not use the 4K allocations but allocates in one step.
-
-function garbagecollector.check(size,criterium)
- if garbagecollector.enabled then
- criterium = criterium or garbagecollector.criterium
- if not size or (criterium and criterium > 0 and size > criterium) then
- if trace_checking then
- local b = collectgarbage("count")
- collectgarbage("collect")
- local a = collectgarbage("count")
- report_memory("forced sweep, collected: %s MB, used: %s MB",round((b-a)/1000),round(a/1000))
- else
- collectgarbage("collect")
- end
- end
- end
-end
-
--- this will move
-
-commands = commands or { }
-
-function commands.showcallbacks()
- local NC, NR, verbatim = context.NC, context.NR, context.type
- context.starttabulate { "|l|l|p|" }
- for name, _ in sortedhash(list) do
- NC() verbatim(name) NC() verbatim(state(name)) NC() context(frozen[name] or "") NC() NR()
- end
- context.stoptabulate()
-end
+if not modules then modules = { } end modules ['luat-cbk'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local insert, remove, find, format = table.insert, table.remove, string.find, string.format
+local collectgarbage, type, next = collectgarbage, type, next
+local round = math.round
+local sortedhash, tohash = table.sortedhash, table.tohash
+
+local trace_checking = false trackers.register("memory.checking", function(v) trace_checking = v end)
+
+local report_callbacks = logs.reporter("system","callbacks")
+local report_memory = logs.reporter("system","memory")
+
+--[[ldx--
+<p>Callbacks are the real asset of <l n='luatex'/>. They permit you to hook
+your own code into the <l n='tex'/> engine. Here we implement a few handy
+auxiliary functions.</p>
+--ldx]]--
+
+callbacks = callbacks or { }
+local callbacks = callbacks
+
+--[[ldx--
+<p>When you (temporarily) want to install a callback function, and after a
+while wants to revert to the original one, you can use the following two
+functions.</p>
+--ldx]]--
+
+local trace_callbacks = false trackers.register("system.callbacks", function(v) trace_callbacks = v end)
+local trace_calls = false -- only used when analyzing performance and initializations
+
+local register_callback = callback.register
+local find_callback = callback.find
+local list_callbacks = callback.list
+
+local frozen, stack, list = { }, { }, callbacks.list
+
+if not list then -- otherwise counters get reset
+
+ list = utilities.storage.allocate(list_callbacks())
+
+ for k, _ in next, list do
+ list[k] = 0
+ end
+
+ callbacks.list = list
+
+end
+
+local delayed = tohash {
+ "buildpage_filter",
+}
+
+
+if trace_calls then
+
+ local functions = { }
+ local original = register_callback
+
+ register_callback = function(name,func)
+ if type(func) == "function" then
+ if functions[name] then
+ functions[name] = func
+ return find_callback(name)
+ else
+ functions[name] = func
+ local cnuf = function(...)
+ list[name] = list[name] + 1
+ return functions[name](...)
+ end
+ return original(name,cnuf)
+ end
+ else
+ return original(name,func)
+ end
+ end
+
+end
+
+local function frozen_message(what,name)
+ report_callbacks("not %s frozen %a to %a",what,name,frozen[name])
+end
+
+local function frozen_callback(name)
+ return nil, format("callback '%s' is frozen to '%s'",name,frozen[name]) -- no formatter yet
+end
+
+local function state(name)
+ local f = find_callback(name)
+ if f == false then
+ return "disabled"
+ elseif f then
+ return "enabled"
+ else
+ return "undefined"
+ end
+end
+
+function callbacks.known(name)
+ return list[name]
+end
+
+function callbacks.report()
+ for name, _ in sortedhash(list) do
+ local str = frozen[name]
+ if str then
+ report_callbacks("%s: %s -> %s",state(name),name,str)
+ else
+ report_callbacks("%s: %s",state(name),name)
+ end
+ end
+end
+
+function callbacks.freeze(name,freeze)
+ freeze = type(freeze) == "string" and freeze
+ if find(name,"%*") then
+ local pattern = name
+ for name, _ in next, list do
+ if find(name,pattern) then
+ frozen[name] = freeze or frozen[name] or "frozen"
+ end
+ end
+ else
+ frozen[name] = freeze or frozen[name] or "frozen"
+ end
+end
+
+function callbacks.register(name,func,freeze)
+ if frozen[name] then
+ if trace_callbacks then
+ frozen_message("registering",name)
+ end
+ return frozen_callback(name)
+ elseif freeze then
+ frozen[name] = type(freeze) == "string" and freeze or "registered"
+ end
+ if delayed[name] and environment.initex then
+ return nil
+ end
+ return register_callback(name,func)
+end
+
+function callback.register(name,func) -- original
+ if not frozen[name] then
+ return register_callback(name,func)
+ elseif trace_callbacks then
+ frozen_message("registering",name)
+ end
+ return frozen_callback(name)
+end
+
+function callbacks.push(name,func)
+ if not frozen[name] then
+ local sn = stack[name]
+ if not sn then
+ sn = { }
+ stack[name] = sn
+ end
+ insert(sn,find_callback(name))
+ register_callback(name, func)
+ elseif trace_callbacks then
+ frozen_message("pushing",name)
+ end
+end
+
+function callbacks.pop(name)
+ if not frozen[name] then
+ local sn = stack[name]
+ if not sn or #sn == 0 then
+ -- some error
+ register_callback(name, nil) -- ! really needed
+ else
+ -- this fails: register_callback(name, remove(stack[name]))
+ local func = remove(sn)
+ register_callback(name, func)
+ end
+ end
+end
+
+if trace_calls then
+ statistics.register("callback details", function()
+ local t = { } -- todo: pass function to register and quit at nil
+ for name, n in sortedhash(list) do
+ if n > 0 then
+ t[#t+1] = format("%s -> %s",name,n)
+ end
+ end
+ return t
+ end)
+end
+
+-- -- somehow crashes later on
+--
+-- callbacks.freeze("find_.*_file","finding file")
+-- callbacks.freeze("read_.*_file","reading file")
+-- callbacks.freeze("open_.*_file","opening file")
+
+--[[ldx--
+<p>The simple case is to remove the callback:</p>
+
+<code>
+callbacks.push('linebreak_filter')
+... some actions ...
+callbacks.pop('linebreak_filter')
+</code>
+
+<p>Often, in such case, another callback or a macro call will pop
+the original.</p>
+
+<p>In practice one will install a new handler, like in:</p>
+
+<code>
+callbacks.push('linebreak_filter', function(...)
+ return something_done(...)
+end)
+</code>
+
+<p>Even more interesting is:</p>
+
+<code>
+callbacks.push('linebreak_filter', function(...)
+ callbacks.pop('linebreak_filter')
+ return something_done(...)
+end)
+</code>
+
+<p>This does a one-shot.</p>
+--ldx]]--
+
+--[[ldx--
+<p>Callbacks may result in <l n='lua'/> doing some hard work
+which takes time and above all resourses. Sometimes it makes
+sense to disable or tune the garbage collector in order to
+keep the use of resources acceptable.</p>
+
+<p>At some point in the development we did some tests with counting
+nodes (in this case 121049).</p>
+
+<table>
+<tr><td>setstepmul</td><td>seconds</td><td>megabytes</td></tr>
+<tr><td>200</td><td>24.0</td><td>80.5</td></tr>
+<tr><td>175</td><td>21.0</td><td>78.2</td></tr>
+<tr><td>150</td><td>22.0</td><td>74.6</td></tr>
+<tr><td>160</td><td>22.0</td><td>74.6</td></tr>
+<tr><td>165</td><td>21.0</td><td>77.6</td></tr>
+<tr><td>125</td><td>21.5</td><td>89.2</td></tr>
+<tr><td>100</td><td>21.5</td><td>88.4</td></tr>
+</table>
+
+<p>The following code is kind of experimental. In the documents
+that describe the development of <l n='luatex'/> we report
+on speed tests. One observation is thta it sometimes helps to
+restart the collector. Okay, experimental code has been removed,
+because messing aroudn with the gc is too unpredictable.</p>
+--ldx]]--
+
+-- For the moment we keep this here and not in util-gbc.lua or so.
+
+utilities = utilities or { }
+utilities.garbagecollector = utilities.garbagecollector or { }
+local garbagecollector = utilities.garbagecollector
+
+garbagecollector.enabled = false -- could become a directive
+garbagecollector.criterium = 4*1024*1024
+
+-- Lua allocates up to 12 times the amount of memory needed for
+-- handling a string, and for large binary chunks (like chinese otf
+-- files) we get a prominent memory consumption. Even when a variable
+-- is nilled, there is some delay in freeing the associated memory (the
+-- hashed string) because if we do the same thing directly afterwards,
+-- we see only a slight increase in memory. For that reason it makes
+-- sense to do a collector pass after a huge file.
+--
+-- test file:
+--
+-- function test()
+-- local b = collectgarbage("count")
+-- local s = io.loaddata("some font table, e.g. a big tmc file")
+-- local a = collectgarbage("count")
+-- print(">>> STATUS",b,a,a-b,#s,1000*(a-b)/#s)
+-- end
+--
+-- test() test() test() test() collectgarbage("collect") test() test() test() test()
+--
+-- As a result of this, LuaTeX now uses an optimized version of f:read("*a"),
+-- one that does not use the 4K allocations but allocates in one step.
+
+function garbagecollector.check(size,criterium)
+ if garbagecollector.enabled then
+ criterium = criterium or garbagecollector.criterium
+ if not size or (criterium and criterium > 0 and size > criterium) then
+ if trace_checking then
+ local b = collectgarbage("count")
+ collectgarbage("collect")
+ local a = collectgarbage("count")
+ report_memory("forced sweep, collected: %s MB, used: %s MB",round((b-a)/1000),round(a/1000))
+ else
+ collectgarbage("collect")
+ end
+ end
+ end
+end
+
+-- this will move
+
+commands = commands or { }
+
+function commands.showcallbacks()
+ local NC, NR, verbatim = context.NC, context.NR, context.type
+ context.starttabulate { "|l|l|p|" }
+ for name, _ in sortedhash(list) do
+ NC() verbatim(name) NC() verbatim(state(name)) NC() context(frozen[name] or "") NC() NR()
+ end
+ context.stoptabulate()
+end