Merge pull request #32 from petersktang/main
Add NSLock to protect lazily loaded tables in multithread setting
This commit is contained in:
@@ -62,6 +62,7 @@ public class MTMathAtomFactory {
|
|||||||
"rfloor" : "\u{230B}"
|
"rfloor" : "\u{230B}"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
private static let delimValueLock = NSLock()
|
||||||
static var _delimValueToName = [String: String]()
|
static var _delimValueToName = [String: String]()
|
||||||
public static var delimValueToName: [String: String] {
|
public static var delimValueToName: [String: String] {
|
||||||
if _delimValueToName.isEmpty {
|
if _delimValueToName.isEmpty {
|
||||||
@@ -78,7 +79,12 @@ public class MTMathAtomFactory {
|
|||||||
}
|
}
|
||||||
output[value] = key
|
output[value] = key
|
||||||
}
|
}
|
||||||
_delimValueToName = output
|
// protect lazily loading table in a multi-thread concurrent environment
|
||||||
|
delimValueLock.lock()
|
||||||
|
defer { delimValueLock.unlock() }
|
||||||
|
if _delimValueToName.isEmpty {
|
||||||
|
_delimValueToName = output
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return _delimValueToName
|
return _delimValueToName
|
||||||
}
|
}
|
||||||
@@ -98,6 +104,7 @@ public class MTMathAtomFactory {
|
|||||||
"widetilde" : "\u{0303}"
|
"widetilde" : "\u{0303}"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
private static let accentValueLock = NSLock()
|
||||||
static var _accentValueToName: [String: String]? = nil
|
static var _accentValueToName: [String: String]? = nil
|
||||||
public static var accentValueToName: [String: String] {
|
public static var accentValueToName: [String: String] {
|
||||||
if _accentValueToName == nil {
|
if _accentValueToName == nil {
|
||||||
@@ -115,7 +122,12 @@ public class MTMathAtomFactory {
|
|||||||
}
|
}
|
||||||
output[value] = key
|
output[value] = key
|
||||||
}
|
}
|
||||||
_accentValueToName = output
|
// protect lazily loading table in a multi-thread concurrent environment
|
||||||
|
accentValueLock.lock()
|
||||||
|
defer { accentValueLock.unlock() }
|
||||||
|
if _accentValueToName == nil {
|
||||||
|
_accentValueToName = output
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return _accentValueToName!
|
return _accentValueToName!
|
||||||
}
|
}
|
||||||
@@ -390,6 +402,7 @@ public class MTMathAtomFactory {
|
|||||||
"scriptscriptstyle" : MTMathStyle(style: .scriptOfScript),
|
"scriptscriptstyle" : MTMathStyle(style: .scriptOfScript),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
private static let textToLatexLock = NSLock()
|
||||||
static var _textToLatexSymbolName: [String: String]? = nil
|
static var _textToLatexSymbolName: [String: String]? = nil
|
||||||
public static var textToLatexSymbolName: [String: String] {
|
public static var textToLatexSymbolName: [String: String] {
|
||||||
get {
|
get {
|
||||||
@@ -413,13 +426,20 @@ public class MTMathAtomFactory {
|
|||||||
}
|
}
|
||||||
output[atom.nucleus] = key
|
output[atom.nucleus] = key
|
||||||
}
|
}
|
||||||
self._textToLatexSymbolName = output
|
// protect lazily loading table in a multi-thread concurrent environment
|
||||||
|
textToLatexLock.lock()
|
||||||
|
defer { textToLatexLock.unlock() }
|
||||||
|
if self._textToLatexSymbolName == nil {
|
||||||
|
self._textToLatexSymbolName = output
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return self._textToLatexSymbolName!
|
return self._textToLatexSymbolName!
|
||||||
}
|
}
|
||||||
set {
|
// make textToLatexSymbolName readonly (allows internal load)
|
||||||
self._textToLatexSymbolName = newValue
|
// entries can be lazily added with NSLock protection.
|
||||||
}
|
// set {
|
||||||
|
// self._textToLatexSymbolName = newValue
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
// public static let sharedInstance = MTMathAtomFactory()
|
// public static let sharedInstance = MTMathAtomFactory()
|
||||||
@@ -603,8 +623,13 @@ public class MTMathAtomFactory {
|
|||||||
e.g. to define a symbol for "lcm" one can call:
|
e.g. to define a symbol for "lcm" one can call:
|
||||||
`MTMathAtomFactory.add(latexSymbol:"lcm", value:MTMathAtomFactory.operatorWithName("lcm", limits: false))` */
|
`MTMathAtomFactory.add(latexSymbol:"lcm", value:MTMathAtomFactory.operatorWithName("lcm", limits: false))` */
|
||||||
public static func add(latexSymbol name: String, value: MTMathAtom) {
|
public static func add(latexSymbol name: String, value: MTMathAtom) {
|
||||||
|
let _ = Self.textToLatexSymbolName
|
||||||
|
// above force textToLatexSymbolName to initialise first, _textToLatexSymbolName also initialized.
|
||||||
|
// protect lazily loading table in a multi-thread concurrent environment
|
||||||
|
textToLatexLock.lock()
|
||||||
|
defer { textToLatexLock.unlock() }
|
||||||
supportedLatexSymbols[name] = value
|
supportedLatexSymbols[name] = value
|
||||||
Self.textToLatexSymbolName[value.nucleus] = name
|
Self._textToLatexSymbolName?[value.nucleus] = name
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a large opertor for the given name. If limits is true, limits are set up on
|
/** Returns a large opertor for the given name. If limits is true, limits are set up on
|
||||||
|
|||||||
@@ -47,14 +47,14 @@ final class MTFontMathTableV2Tests: XCTestCase {
|
|||||||
func helperConcurrentMTFontMathTableV2(_ count: Int, mtfont: MTFontV2, in group: DispatchGroup, on queue: DispatchQueue) {
|
func helperConcurrentMTFontMathTableV2(_ count: Int, mtfont: MTFontV2, in group: DispatchGroup, on queue: DispatchQueue) {
|
||||||
let workitem = DispatchWorkItem {
|
let workitem = DispatchWorkItem {
|
||||||
let mTable = mtfont.mathTable
|
let mTable = mtfont.mathTable
|
||||||
// let values = [
|
let values = [
|
||||||
// mTable?.fractionNumeratorDisplayStyleShiftUp,
|
mTable?.fractionNumeratorDisplayStyleShiftUp,
|
||||||
// mTable?.fractionNumeratorShiftUp,
|
mTable?.fractionNumeratorShiftUp,
|
||||||
// mTable?.fractionDenominatorDisplayStyleShiftDown,
|
mTable?.fractionDenominatorDisplayStyleShiftDown,
|
||||||
// mTable?.fractionDenominatorShiftDown,
|
mTable?.fractionDenominatorShiftDown,
|
||||||
// mTable?.fractionNumeratorDisplayStyleGapMin,
|
mTable?.fractionNumeratorDisplayStyleGapMin,
|
||||||
// mTable?.fractionNumeratorGapMin,
|
mTable?.fractionNumeratorGapMin,
|
||||||
// ].compactMap{$0}
|
].compactMap{$0}
|
||||||
// if count % 50 == 0 {
|
// if count % 50 == 0 {
|
||||||
// print(values) // accessed these values on global thread.
|
// print(values) // accessed these values on global thread.
|
||||||
// }
|
// }
|
||||||
@@ -62,16 +62,16 @@ final class MTFontMathTableV2Tests: XCTestCase {
|
|||||||
}
|
}
|
||||||
workitem.notify(queue: .main) { [weak self] in
|
workitem.notify(queue: .main) { [weak self] in
|
||||||
// print("\(Thread.isMainThread ? "main" : "global") completed .....")
|
// print("\(Thread.isMainThread ? "main" : "global") completed .....")
|
||||||
// let mTable = mtfont.mathTable
|
let mTable = mtfont.mathTable
|
||||||
if count % 70 == 0 {
|
if count % 70 == 0 {
|
||||||
// let values = [
|
let values = [
|
||||||
// mTable?.fractionNumeratorDisplayStyleShiftUp,
|
mTable?.fractionNumeratorDisplayStyleShiftUp,
|
||||||
// mTable?.fractionNumeratorShiftUp,
|
mTable?.fractionNumeratorShiftUp,
|
||||||
// mTable?.fractionDenominatorDisplayStyleShiftDown,
|
mTable?.fractionDenominatorDisplayStyleShiftDown,
|
||||||
// mTable?.fractionDenominatorShiftDown,
|
mTable?.fractionDenominatorShiftDown,
|
||||||
// mTable?.fractionNumeratorDisplayStyleGapMin,
|
mTable?.fractionNumeratorDisplayStyleGapMin,
|
||||||
// mTable?.fractionNumeratorGapMin,
|
mTable?.fractionNumeratorGapMin,
|
||||||
// ].compactMap{$0}
|
].compactMap{$0}
|
||||||
// if count % 50 == 0 {
|
// if count % 50 == 0 {
|
||||||
// print(values)
|
// print(values)
|
||||||
// }
|
// }
|
||||||
|
|||||||
Reference in New Issue
Block a user