(root)/
harfbuzz-8.3.0/
test/
api/
test-multithread.c
       1  /*
       2   * Copyright © 2018  Ebrahim Byagowi
       3   *
       4   *  This is part of HarfBuzz, a text shaping library.
       5   *
       6   * Permission is hereby granted, without written agreement and without
       7   * license or royalty fees, to use, copy, modify, and distribute this
       8   * software and its documentation for any purpose, provided that the
       9   * above copyright notice and the following two paragraphs appear in
      10   * all copies of this software.
      11   *
      12   * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
      13   * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
      14   * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
      15   * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
      16   * DAMAGE.
      17   *
      18   * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
      19   * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
      20   * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
      21   * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
      22   * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
      23   *
      24   */
      25  
      26  #include <pthread.h>
      27  
      28  #include <hb.h>
      29  #include <hb-ft.h>
      30  #include <hb-ot.h>
      31  
      32  #include "hb-test.h"
      33  
      34  static const char *font_path = "fonts/Inconsolata-Regular.abc.ttf";
      35  static const char *text = "abc";
      36  
      37  static int num_threads = 30;
      38  static int num_iters = 200;
      39  
      40  static hb_font_t *font;
      41  static hb_buffer_t *ref_buffer;
      42  
      43  static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
      44  
      45  static void
      46  fill_the_buffer (hb_buffer_t *buffer)
      47  {
      48    hb_buffer_add_utf8 (buffer, text, -1, 0, -1);
      49    hb_buffer_guess_segment_properties (buffer);
      50    hb_shape (font, buffer, NULL, 0);
      51  }
      52  
      53  static void
      54  validity_check (hb_buffer_t *buffer) {
      55    if (hb_buffer_diff (ref_buffer, buffer, (hb_codepoint_t) -1, 0))
      56    {
      57      fprintf (stderr, "One of the buffers was different from the reference.\n");
      58      char out[255];
      59  
      60      hb_buffer_serialize_glyphs (buffer, 0, hb_buffer_get_length (ref_buffer),
      61  				out, sizeof (out), NULL,
      62  				font, HB_BUFFER_SERIALIZE_FORMAT_TEXT,
      63  				HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES);
      64      fprintf (stderr, "Actual:   %s\n", out);
      65  
      66      hb_buffer_serialize_glyphs (ref_buffer, 0, hb_buffer_get_length (ref_buffer),
      67  				out, sizeof (out), NULL,
      68  				font, HB_BUFFER_SERIALIZE_FORMAT_TEXT,
      69  				HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES);
      70      fprintf (stderr, "Expected: %s\n", out);
      71  
      72      exit (1);
      73    }
      74  }
      75  
      76  static void *
      77  thread_func (void *data)
      78  {
      79    hb_buffer_t *buffer = (hb_buffer_t *) data;
      80  
      81    pthread_mutex_lock (&mutex);
      82    pthread_mutex_unlock (&mutex);
      83  
      84    int i;
      85    for (i = 0; i < num_iters; i++)
      86    {
      87      hb_buffer_clear_contents (buffer);
      88      fill_the_buffer (buffer);
      89      validity_check (buffer);
      90    }
      91  
      92    return 0;
      93  }
      94  
      95  static void
      96  test_body (void)
      97  {
      98    int i;
      99    pthread_t *threads = calloc (num_threads, sizeof (pthread_t));
     100    hb_buffer_t **buffers = calloc (num_threads, sizeof (hb_buffer_t *));
     101  
     102    pthread_mutex_lock (&mutex);
     103  
     104    for (i = 0; i < num_threads; i++)
     105    {
     106      hb_buffer_t *buffer = hb_buffer_create ();
     107      buffers[i] = buffer;
     108      pthread_create (&threads[i], NULL, thread_func, buffer);
     109    }
     110  
     111    /* Let them loose! */
     112    pthread_mutex_unlock (&mutex);
     113  
     114    for (i = 0; i < num_threads; i++)
     115    {
     116      pthread_join (threads[i], NULL);
     117      hb_buffer_destroy (buffers[i]);
     118    }
     119  
     120    free (buffers);
     121    free (threads);
     122  }
     123  
     124  int
     125  main (int argc, char **argv)
     126  {
     127    hb_test_init (&argc, &argv);
     128  
     129    char *path = argc > 1 && *argv[1] ? argv[1] : (char *) font_path;
     130    if (argc > 2)
     131      num_threads = atoi (argv[2]);
     132    if (argc > 3)
     133      num_iters = atoi (argv[3]);
     134    if (argc > 4)
     135      text = argv[4];
     136  
     137    /* Dummy call to alleviate _guess_segment_properties thread safety-ness
     138     * https://github.com/harfbuzz/harfbuzz/issues/1191 */
     139    hb_language_get_default ();
     140  
     141    hb_face_t *face = hb_test_open_font_file (path);
     142    font = hb_font_create (face);
     143  
     144    /* Fill the reference */
     145    ref_buffer = hb_buffer_create ();
     146    fill_the_buffer (ref_buffer);
     147  
     148    /* Unnecessary, since version 2 it is ot-font by default */
     149    hb_ot_font_set_funcs (font);
     150    test_body ();
     151  
     152    /* Test hb-ft in multithread */
     153    hb_ft_font_set_funcs (font);
     154    test_body ();
     155  
     156    hb_buffer_destroy (ref_buffer);
     157  
     158    hb_font_destroy (font);
     159    hb_face_destroy (face);
     160  
     161    return 0;
     162  }