diff options
Diffstat (limited to 'tex/context/base/luat-cbk.lua')
-rw-r--r-- | tex/context/base/luat-cbk.lua | 640 |
1 files changed, 320 insertions, 320 deletions
diff --git a/tex/context/base/luat-cbk.lua b/tex/context/base/luat-cbk.lua index 4a88cfed7..5aa12005b 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 |