@@ -2151,14 +2151,30 @@ function MOI.optimize!(model::Optimizer)
2151
2151
ret = Highs_zeroAllClocks (model)
2152
2152
_check_ret (ret)
2153
2153
end
2154
+ has_default_callback = model. callback_data === nothing
2155
+ if has_default_callback
2156
+ # From the docstring of disable_sigint, "External functions that do not
2157
+ # call julia code or julia runtime automatically disable sigint during
2158
+ # their execution." We don't want this though! We want to be able to
2159
+ # SIGINT HiGHS, and then catch it as an interrupt. As a hack, until
2160
+ # Julia introduces an interruptible ccall --- which it likely won't
2161
+ # https://github.com/JuliaLang/julia/issues/2622 --- set a null
2162
+ # callback.
2163
+ MOI. set (model, CallbackFunction (), (args... ) -> Cint (0 ))
2164
+ end
2154
2165
# if `Highs_run` implicitly uses memory or other resources owned by `model`, preserve it
2155
2166
GC. @preserve model begin
2156
2167
# allow Julia to GC while this thread is in `Highs_run`
2157
2168
gc_state = ccall (:jl_gc_safe_enter , Int8, ())
2158
- ret = Highs_run (model)
2169
+ # We disable sigint here so that it can be called only when we are in a
2170
+ # try-catch of our CallbackFunction.
2171
+ ret = disable_sigint (() -> Highs_run (model))
2159
2172
# leave GC-safe region, waiting for GC to complete if it's running
2160
2173
ccall (:jl_gc_safe_leave , Cvoid, (Int8,), gc_state)
2161
2174
end
2175
+ if has_default_callback
2176
+ MOI. set (model, CallbackFunction (), nothing )
2177
+ end
2162
2178
_store_solution (model, ret)
2163
2179
# TODO (odow): resetting the bounds here invalidates previously stored
2164
2180
# solutions.
@@ -3088,6 +3104,8 @@ end
3088
3104
kHighsCallbackMipImprovingSolution,
3089
3105
# kHighsCallbackMipLogging,
3090
3106
kHighsCallbackMipInterrupt,
3107
+ kHighsCallbackMipGetCutPool,
3108
+ kHighsCallbackMipDefineLazyConstraints,
3091
3109
],
3092
3110
) <: MOI.AbstractModelAttribute
3093
3111
@@ -3135,24 +3153,41 @@ function CallbackFunction()
3135
3153
kHighsCallbackMipImprovingSolution,
3136
3154
# kHighsCallbackMipLogging,
3137
3155
kHighsCallbackMipInterrupt,
3156
+ kHighsCallbackMipGetCutPool,
3157
+ kHighsCallbackMipDefineLazyConstraints,
3138
3158
])
3139
3159
end
3140
3160
3141
3161
function _cfn_user_callback (
3142
3162
callback_type:: Cint ,
3143
3163
message:: Ptr{Cchar} ,
3144
- p_data_out:: Ptr{HiGHS.HighsCallbackDataOut} ,
3145
- p_data_in:: Ptr{HiGHS.HighsCallbackDataIn} ,
3146
- user_callback_data:: Ptr{Cvoid} ,
3147
- )
3148
- user_data = unsafe_pointer_to_objref (user_callback_data):: _CallbackData
3149
- terminate = user_data. f (
3150
- callback_type,
3151
- message,
3152
- unsafe_load (p_data_out):: HiGHS.HighsCallbackDataOut ,
3164
+ p_data_out:: Ptr{HighsCallbackDataOut} ,
3165
+ p_data_in:: Ptr{HighsCallbackDataIn} ,
3166
+ p_user_data:: Ptr{Cvoid} ,
3167
+ )
3168
+ user_data = unsafe_pointer_to_objref (p_user_data):: _CallbackData
3169
+ data_out = unsafe_load (p_data_out):: HighsCallbackDataOut
3170
+ if callback_type in (
3171
+ kHighsCallbackSimplexInterrupt,
3172
+ kHighsCallbackIpmInterrupt,
3173
+ kHighsCallbackMipInterrupt,
3153
3174
)
3154
- if p_data_in != C_NULL
3155
- unsafe_store! (p_data_in, HighsCallbackDataIn (terminate))
3175
+ @assert p_data_in != = C_NULL
3176
+ try
3177
+ reenable_sigint () do
3178
+ terminate = user_data. f (callback_type, message, data_out)
3179
+ unsafe_store! (p_data_in, HighsCallbackDataIn (terminate))
3180
+ return
3181
+ end
3182
+ catch err
3183
+ unsafe_store! (p_data_in, HighsCallbackDataIn (Cint (1 )))
3184
+ if ! (err isa InterruptException)
3185
+ rethrow (err)
3186
+ end
3187
+ end
3188
+ else
3189
+ # Ignore what the user says about terminating
3190
+ _ = user_data. f (callback_type, message, data_out)
3156
3191
end
3157
3192
return
3158
3193
end
@@ -3179,6 +3214,17 @@ function MOI.set(model::Optimizer, attr::CallbackFunction, f::Function)
3179
3214
return
3180
3215
end
3181
3216
3217
+ function MOI. set (model:: Optimizer , attr:: CallbackFunction , :: Nothing )
3218
+ model. callback_data = nothing
3219
+ ret = Highs_setCallback (model, C_NULL , C_NULL )
3220
+ _check_ret (ret)
3221
+ for callback_type in attr. callback_types
3222
+ ret = Highs_stopCallback (model, callback_type)
3223
+ _check_ret (ret)
3224
+ end
3225
+ return
3226
+ end
3227
+
3182
3228
function MOI. write_to_file (model:: Optimizer , filename:: String )
3183
3229
ret = Highs_writeModel (model, filename)
3184
3230
_check_ret (ret)
0 commit comments