[liblouis-liblouisxml] Re: Potential memory leak around using table resolvers

  • From: Bert Frees <bertfrees@xxxxxxxxx>
  • To: "liblouis-liblouisxml@xxxxxxxxxxxxx" <liblouis-liblouisxml@xxxxxxxxxxxxx>
  • Date: Mon, 29 Aug 2016 22:44:32 +0200

Thanks for the example. Yeah, I had expected something like this, but I
don't know if I like it. I need to think about it...

2016-08-29 21:19 GMT+02:00 Michael Whapples <dmarc-noreply@xxxxxxxxxxxxx>:

Well I do have a thought as to how it can be achieved with a single
function.

Think of tableList and base as being the identifier for the function call.
Well for the purpose of code examples I will only use tableList. You need
to keep track of how far through tableList you have got and this can be
stored as an integer. As the identifier maps to a single integer value we
could use a map. Similarly we need to hold on to one result for each
identifier, so another map, or work out a way to combine. Java code might
look like:
public class TableResolver {
    public final static String FINISHED = "";
    // Keep the string for finished in memory
    private static Map<String, Integer> iterState = new HashMap<>();
    private static Map<String, String> iterResult = new HashMap<>();
    public String resolve(String tableList, String base) {
        // check if previously called for this tableList and ideally base
        int index = TableResolver.iterState.getOrDefault(tableList, new
Integer(0));
        if (index == tableList.length()) {
            // Finished processing
            iterState.remove(tableList)
            iterResult.remove(tableList);
            return TableResolver.FINISHED;
        }
        String result = null;
        // Do your table resolving assigning to result only if table is
found
        // index indicates where to start processing from in tableList
        // Leave result = null if there is an error, or just return null
        // Also update index
        if (result != null) {
            TableResolver.iterState.put(tableList, index);
            TableResolver.iterResult.put(tableList, result);
        }
        return result;
    }
}

Multi-threading might pose a slight issue for this one, but ideally that
could be dealt with by LibLouis, halting a thread requesting the same
tableList and base until the resolver has finished resolving it. The halted
thread when allowed to continue would not need to call the table resolver
as LibLouis already knows the actual table file name and has compiled them.

So through this we have a iterator for resolving tables with a single
function of signature:
char* resolveTableIter(char* tableList, char* base). LibLouis would
continually call this until it recieves an empty string back. If it
recieves a NULL value back then it has a error in tableList and should
abort.
For a description of the software, to download it and links to
project pages go to http://liblouis.org

Other related posts: