dds-bridge-sys 3.0.0

Generated bindings to DDS, the double dummy solver for bridge
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
# DDS API Migration Guide

This guide helps you migrate from the legacy C API to the modern C++ API.

## Table of Contents
- [Overview]#overview
- [Why Migrate?]#why-migrate
- [API Comparison]#api-comparison
- [Migration Examples]#migration-examples
- [Common Patterns]#common-patterns
- [Performance Notes]#performance-notes
- [FAQ]#faq

## Overview

DDS provides two API layers:

### Modern C++ API (Recommended)
- **Header:** `#include <dds/dds.hpp>`
- **Core Type:** `SolverContext` - instance-scoped solver state
- **Configuration:** `SolverConfig` - per-context settings
- **Memory Management:** RAII - automatic cleanup
- **Threading:** Implicit - one context per thread

### Legacy C API (Backward Compatible)
- **Header:** `#include <api/dll.h>`
- **State:** Global and thread-local
- **Configuration:** `SetThreading()`, `SetResources()`, etc.
- **Memory Management:** Manual - `FreeMemory()` required
- **Threading:** Explicit backend selection

## Why Migrate?

### Benefits of Modern C++ API

| Feature | Modern API | Legacy API |
|---------|-----------|------------|
| **Memory Safety** | RAII automatic cleanup | Manual `FreeMemory()` calls |
| **Thread Safety** | One context per thread | Global state with locking |
| **Configuration** | Per-instance via `SolverConfig` | Global via `SetResources()` |
| **TT Lifecycle** | Explicit control (`reset_for_solve()`) | Implicit global pool |
| **Performance** | Equal or better | Baseline |
| **Flexibility** | Multiple contexts, different configs | Single global config |

### Key Advantages

1. **No resource leaks** - Context automatically cleans up when destroyed
2. **Better multithreading** - Each thread owns its context (no contention)
3. **Explicit lifecycle** - You control when to reset or clear transposition tables
4. **Type safety** - C++ types and compile-time checks
5. **Modern patterns** - Smart pointers, RAII, standard library integration

## API Comparison

### Deprecated Functions and Replacements

| Legacy Function | Modern Replacement | Notes |
|----------------|-------------------|-------|
| `SetThreading(code)` | Create one `SolverContext` per thread | Threading is implicit |
| `SetMaxThreads(n)` | One `SolverContext` per worker thread | Control thread count in your app |
| `SetResources(mem, threads)` | `SolverConfig::tt_mem_maximum_mb_` + per-thread contexts | Split memory and thread control |
| `FreeMemory()` | Context destruction | Automatic via RAII |

### Core Solving Functions

The solving functions remain compatible but have new overloads:

```cpp
// Legacy C API
int SolveBoard(struct Deal dl, int target, int solutions, int mode,
               struct FutureTricks* futp, int thrId);

// Modern C++ API - new overload
int SolveBoard(SolverContext& ctx, const Deal& dl, int target,
               int solutions, int mode, struct FutureTricks* futp);
```

## Migration Examples

### Example 1: Single Board Solve

#### Before (Legacy C API)
```c
#include <api/dll.h>

int main() {
    // Global configuration
    SetMaxThreads(4);
    SetResources(2000, 4);
    
    // Solve a board
    Deal dl;
    // ... initialize dl ...
    
    FutureTricks fut;
    int res = SolveBoard(dl, -1, 3, 0, &fut, 0);
    
    if (res == RETURN_NO_FAULT) {
        // Use results
        printf("Tricks: %d\n", fut.score[0]);
    }
    
    // Manual cleanup
    FreeMemory();
    return 0;
}
```

#### After (Modern C++ API)
```cpp
#include <dds/dds.hpp>
#include <memory>

int main() {
    // Per-instance configuration
    SolverConfig cfg;
    cfg.tt_kind_ = TTKind::Large;
    cfg.tt_mem_default_mb_ = 2000;
    cfg.tt_mem_maximum_mb_ = 2000;
    
    // Create context
    SolverContext ctx(cfg);
    
    // Solve a board
    Deal dl;
    // ... initialize dl ...
    
    FutureTricks fut;
    int res = SolveBoard(ctx, dl, -1, 3, 0, &fut);
    
    if (res == RETURN_NO_FAULT) {
        // Use results
        std::cout << "Tricks: " << fut.score[0] << "\n";
    }
    
    // Automatic cleanup when ctx goes out of scope
    return 0;
}
```

### Example 2: Multiple Boards with TT Reuse

#### Before (Legacy C API)
```c
#include <api/dll.h>

void solve_many_boards(Deal* boards, int count) {
    SetResources(2000, 4);
    
    for (int i = 0; i < count; i++) {
        FutureTricks fut;
        SolveBoard(boards[i], -1, 3, 0, &fut, 0);
        // Process results...
    }
    
    FreeMemory();
}
```

#### After (Modern C++ API)
```cpp
#include <dds/dds.hpp>

void solve_many_boards(const std::vector<Deal>& boards) {
    SolverConfig cfg;
    cfg.tt_kind_ = TTKind::Large;
    cfg.tt_mem_default_mb_ = 2000;
    cfg.tt_mem_maximum_mb_ = 2000;
    
    SolverContext ctx(cfg);
    
    for (const auto& board : boards) {
        FutureTricks fut;
        SolveBoard(ctx, board, -1, 3, 0, &fut);
        // Process results...
        // TT accumulates knowledge across boards
    }
    
    // Optional: clear TT between unrelated problems
    // ctx.reset_for_solve();
    
    // Automatic cleanup
}
```

### Example 3: Multithreaded Processing

#### Before (Legacy C API)
```c
#include <api/dll.h>
#include <pthread.h>

void* worker(void* arg) {
    int thrId = *(int*)arg;
    Deal dl;
    // ... initialize dl ...
    
    FutureTricks fut;
    SolveBoard(dl, -1, 3, 0, &fut, thrId);  // Thread ID required
    return NULL;
}

int main() {
    SetMaxThreads(4);
    SetResources(2000, 4);
    
    pthread_t threads[4];
    int ids[4] = {0, 1, 2, 3};
    
    for (int i = 0; i < 4; i++) {
        pthread_create(&threads[i], NULL, worker, &ids[i]);
    }
    
    for (int i = 0; i < 4; i++) {
        pthread_join(threads[i], NULL);
    }
    
    FreeMemory();
    return 0;
}
```

#### After (Modern C++ API)
```cpp
#include <dds/dds.hpp>
#include <thread>
#include <vector>

void worker(Deal dl) {
    // Each thread creates its own context
    SolverConfig cfg;
    cfg.tt_kind_ = TTKind::Large;
    cfg.tt_mem_default_mb_ = 500;   // 500MB per thread (default TT size)
    cfg.tt_mem_maximum_mb_ = 500;   // Cap TT size at 500MB per thread
    
    SolverContext ctx(cfg);
    
    FutureTricks fut;
    SolveBoard(ctx, dl, -1, 3, 0, &fut);
    // Process results...
    
    // Automatic cleanup when thread exits
}

int main() {
    std::vector<Deal> deals;
    // ... initialize deals ...
    
    std::vector<std::thread> threads;
    for (const auto& dl : deals) {
        threads.emplace_back(worker, dl);
    }
    
    for (auto& t : threads) {
        t.join();
    }
    
    return 0;
}
```

## Common Patterns

### Pattern 1: Reusable Context for Batch Processing

```cpp
class BatchSolver
{
  public:
    BatchSolver() 
    : ctx_(default_config())
    {
    }
    
    auto solve(const Deal& dl) -> FutureTricks
    {
        FutureTricks fut;
        SolveBoard(ctx_, dl, -1, 3, 0, &fut);
        return fut;
    }
    
    auto reset() -> void
    {
        ctx_.reset_for_solve();  // Clear TT for new problem set
    }
    
  private:
    SolverContext ctx_;
    
    static auto default_config() -> SolverConfig
    {
        SolverConfig cfg;
        cfg.tt_kind_ = TTKind::Large;
        cfg.tt_mem_default_mb_ = 2000;
        cfg.tt_mem_maximum_mb_ = 2000;
        return cfg;
    }
};
```

### Pattern 2: Conditional TT Management

```cpp
void solve_tournament(const std::vector<Deal>& boards) {
    SolverContext ctx;
    
    for (size_t i = 0; i < boards.size(); i++) {
        FutureTricks fut;
        SolveBoard(ctx, boards[i], -1, 3, 0, &fut);
        
        // Clear TT between rounds but not within rounds
        if ((i + 1) % 32 == 0) {
            ctx.reset_for_solve();  // New round, unrelated boards
        }
    }
}
```

### Pattern 3: Memory-Constrained Environments

```cpp
SolverConfig make_small_config() {
    SolverConfig cfg;
    cfg.tt_kind_ = TTKind::Small;      // Use small TT implementation
    cfg.tt_mem_default_mb_ = 100;      // Default TT size 100MB
    cfg.tt_mem_maximum_mb_ = 100;      // Hard cap 100MB
    return cfg;
}

void solve_on_embedded(const Deal& dl) {
    SolverContext ctx(make_small_config());
    FutureTricks fut;
    SolveBoard(ctx, dl, -1, 3, 0, &fut);
}
```

## Performance Notes

### Memory Usage
- **Legacy API**: Global pool shared across threads
- **Modern API**: Per-context allocation (multiply by thread count)

**Recommendation**: In multithreaded scenarios, reduce `tt_mem_maximum_mb_` per context to avoid over-allocation.

### Transposition Table Efficiency
The modern API gives you explicit control over TT lifecycle:

```cpp
SolverContext ctx;

// Scenario 1: Related boards (same deal, different contracts)
// Keep TT - it accumulates useful positions
for (auto contract : contracts) {
    solve_with_contract(ctx, deal, contract);
    // NO reset - TT knowledge carries over
}

// Scenario 2: Unrelated boards
// Reset TT - old positions won't help
for (auto deal : unrelated_deals) {
    ctx.reset_for_solve();  // Clear between deals
    solve_board(ctx, deal);
}
```

### Threading Overhead
- **Legacy API**: Locking on shared global state
- **Modern API**: No locking (each thread owns its context)

Result: Better parallelism with modern API.

## FAQ

### Q: Will the legacy C API be removed?
**A:** No. It remains supported indefinitely for binary compatibility. However, new features may only appear in the modern API.

### Q: Can I mix both APIs in the same program?
**A:** Yes, but not recommended. Choose one approach for consistency. The modern API is preferred for new code.

### Q: Do I need to change my build system?
**A:** No. Just update your `#include` directive and use the new API. Both APIs link against the same library.

### Q: What about C-only projects?
**A:** The legacy C API remains fully supported. Consider wrapping the modern C++ API if you can link against C++.

### Q: Are there performance differences?
**A:** The modern API is equal or slightly better due to reduced locking and better cache locality. Solve quality is identical.

### Q: How do I migrate incrementally?
**A:** 
1. Keep using legacy API with deprecation warnings
2. Add `#include <dds/dds.hpp>` alongside `<api/dll.h>`
3. Migrate one function/module at a time
4. Remove legacy includes once complete

### Q: What if I encounter issues?
**A:** Report issues on GitHub. The legacy API will remain functional while you migrate.

## Additional Resources

- [Legacy C API Reference]legacy_c_api.md - Full documentation of deprecated functions
- [SolverContext Documentation]../library/src/README_SolverContext.md - Modern API details
- [Build System Guide]BUILD_SYSTEM.md - Bazel configuration
- [Examples]../examples/ - Sample programs using both APIs

## Summary

| If you need... | Use... |
|----------------|--------|
| Simple single-threaded solving | Modern API - simplest, safest |
| Batch processing with TT reuse | Modern API - explicit control |
| Multi-threaded solving | Modern API - better parallelism |
| C-only compatibility | Legacy API - still supported |
| Existing code maintenance | Legacy API - no rush to migrate |

**Recommendation for new projects:** Use the modern C++ API with `SolverContext`. It's safer, clearer, and more flexible.